blob: 5002391f61e24abc24bdcae19d728510d020c8af [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800159
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000161 FakeInputDispatcherPolicy() = default;
162 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800163
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800164 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700166 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& keyEvent = static_cast<const KeyEvent&>(event);
170 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(keyEvent.getAction(), args.action);
172 });
Jackal Guof9696682018-10-05 12:23:23 +0800173 }
174
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
176 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700177 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700178 EXPECT_EQ(event.getDisplayId(), args.displayId);
179
180 const auto& motionEvent = static_cast<const MotionEvent&>(event);
181 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
182 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000183 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
186 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700190 void assertFilterInputEventWasNotCalled() {
191 std::scoped_lock lock(mLock);
192 ASSERT_EQ(nullptr, mFilteredEvent);
193 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700196 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 ASSERT_TRUE(mConfigurationChangedTime)
198 << "Timed out waiting for configuration changed call";
199 ASSERT_EQ(*mConfigurationChangedTime, when);
200 mConfigurationChangedTime = std::nullopt;
201 }
202
203 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800206 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
208 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
209 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
210 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
211 mLastNotifySwitch = std::nullopt;
212 }
213
chaviwfd6d3512019-03-25 13:23:49 -0700214 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800216 ASSERT_EQ(touchedToken, mOnPointerDownToken);
217 mOnPointerDownToken.clear();
218 }
219
220 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mOnPointerDownToken == nullptr)
223 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700224 }
225
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700226 // This function must be called soon after the expected ANR timer starts,
227 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700229 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 std::unique_lock lock(mLock);
232 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800234 ASSERT_NO_FATAL_FAILURE(
235 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500236 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
238
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000239 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800240 const sp<WindowInfoHandle>& window) {
241 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
242 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
243 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 }
245
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
247 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000248 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 std::unique_lock lock(mLock);
250 android::base::ScopedLockAssertion assumeLocked(mLock);
251 AnrResult result;
252 ASSERT_NO_FATAL_FAILURE(result =
253 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000254 ASSERT_EQ(expectedToken, result.token);
255 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500256 }
257
Prabir Pradhanedd96402022-02-15 01:46:16 -0800258 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 std::unique_lock lock(mLock);
261 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
263 const auto& [token, _] = result;
264 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000265 }
266
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 std::unique_lock lock(mLock);
270 android::base::ScopedLockAssertion assumeLocked(mLock);
271 AnrResult result;
272 ASSERT_NO_FATAL_FAILURE(
273 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000274 ASSERT_EQ(expectedToken, result.token);
275 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 }
277
278 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 sp<IBinder> getResponsiveWindowToken() {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
283 const auto& [token, _] = result;
284 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
287 void assertNotifyAnrWasNotCalled() {
288 std::scoped_lock lock(mLock);
289 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_TRUE(mAnrWindows.empty());
291 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 << "ANR was not called, but please also consume the 'connection is responsive' "
293 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700294 }
295
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::unique_lock lock(mLock);
298 base::ScopedLockAssertion assumeLocked(mLock);
299
300 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
301 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 enabled;
304 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
306 << ") to be called.";
307 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 auto request = *mPointerCaptureRequest;
310 mPointerCaptureRequest.reset();
311 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
313
314 void assertSetPointerCaptureNotCalled() {
315 std::unique_lock lock(mLock);
316 base::ScopedLockAssertion assumeLocked(mLock);
317
318 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
325
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700326 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
327 const sp<IBinder>& targetToken) {
328 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800329 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800331 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800332 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800333 }
334
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800335 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338 std::optional<sp<IBinder>> receivedToken =
339 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
340 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000341 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800342 ASSERT_EQ(token, *receivedToken);
343 }
344
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800345 /**
346 * Set policy timeout. A value of zero means next key will not be intercepted.
347 */
348 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
349 mInterceptKeyTimeout = timeout;
350 }
351
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700352 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
353
Josep del Riob3981622023-04-18 15:49:45 +0000354 void assertUserActivityPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
357 }
358
359 void assertUserActivityNotPoked() {
360 std::scoped_lock lock(mLock);
361 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
362 }
363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000364 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000365 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
366 }
367
368 void assertNotifyDeviceInteractionWasNotCalled() {
369 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
370 }
371
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000372 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
373 std::scoped_lock lock(mLock);
374 mUnhandledKeyHandler = handler;
375 }
376
377 void assertUnhandledKeyReported(int32_t keycode) {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380 std::optional<int32_t> unhandledKeycode =
381 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
382 mNotifyUnhandledKey);
383 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
384 ASSERT_EQ(unhandledKeycode, keycode);
385 }
386
387 void assertUnhandledKeyNotReported() {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<int32_t> unhandledKeycode =
391 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
392 mNotifyUnhandledKey);
393 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
394 }
395
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::mutex mLock;
398 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
399 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
400 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
401 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800402
Prabir Pradhan99987712020-11-10 18:43:05 -0800403 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000404
405 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800406
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700407 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700408 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800409 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
410 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800412 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
413 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700414
arthurhungf452d0b2021-01-06 00:19:52 +0800415 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800416 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000417 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800418
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800419 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
420
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700421 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000425 std::condition_variable mNotifyUnhandledKey;
426 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
427 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 return std::nullopt;
472 }
473 T item = storage.front();
474 storage.pop();
475 return std::make_optional(item);
476 }
477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800480 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 }
482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000483 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 ASSERT_TRUE(pid.has_value());
487 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000492 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 mNotifyAnr.notify_all();
497 }
498
499 void notifyNoFocusedWindowAnr(
500 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
501 std::scoped_lock lock(mLock);
502 mAnrApplications.push(applicationHandle);
503 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800506 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
507 std::scoped_lock lock(mLock);
508 mBrokenInputChannels.push(connectionToken);
509 mNotifyInputChannelBroken.notify_all();
510 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700513
Chris Yef59a2f42020-10-16 12:55:26 -0700514 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
515 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
516 const std::vector<float>& values) override {}
517
518 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
519 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000520
Chris Yefb552902021-02-03 17:18:37 -0800521 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
522
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700524 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700526 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
528 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800529 break;
530 }
531
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700532 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
534 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800535 break;
536 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700537 default: {
538 ADD_FAILURE() << "Should only filter keys or motions";
539 break;
540 }
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 return true;
543 }
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
546 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800547 // Clear intercept state when we handled the event.
548 mInterceptKeyTimeout = 0ms;
549 }
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600552 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
556 // Clear intercept state so we could dispatch the event in next wake.
557 mInterceptKeyTimeout = 0ms;
558 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 }
560
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000563 std::scoped_lock lock(mLock);
564 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
565 mNotifyUnhandledKey.notify_all();
566 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Harry Cutts33476232023-01-30 19:57:29 +0000575 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576 }
577
Josep del Riob3981622023-04-18 15:49:45 +0000578 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
579 std::scoped_lock lock(mLock);
580 mPokedUserActivity = true;
581 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700583 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
584 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
585 }
586
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600587 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700588 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700589 mOnPointerDownToken = newToken;
590 }
591
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000592 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800593 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000594 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800595 mPointerCaptureChangedCondition.notify_all();
596 }
597
arthurhungf452d0b2021-01-06 00:19:52 +0800598 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
599 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800600 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800601 mDropTargetWindowToken = token;
602 }
603
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000604 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000605 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000606 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
607 }
608
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700609 void assertFilterInputEventWasCalledInternal(
610 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700611 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800612 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700613 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800614 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800615 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700617} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619// --- InputDispatcherTest ---
620
621class InputDispatcherTest : public testing::Test {
622protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000623 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700624 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000626 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000627 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700628 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
629
Harry Cutts101ee9b2023-07-06 18:04:14 +0000630 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000631 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700632 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633 }
634
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000635 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700636 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000637 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700638 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800639 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700640
641 /**
642 * Used for debugging when writing the test
643 */
644 void dumpDispatcherState() {
645 std::string dump;
646 mDispatcher->dump(dump);
647 std::stringstream ss(dump);
648 std::string to;
649
650 while (std::getline(ss, to, '\n')) {
651 ALOGE("%s", to.c_str());
652 }
653 }
Vishnu Nair958da932020-08-21 17:12:37 -0700654
Chavi Weingarten847e8512023-03-29 00:26:09 +0000655 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700656 FocusRequest request;
657 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000658 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700659 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
660 request.displayId = window->getInfo()->displayId;
661 mDispatcher->setFocusedWindow(request);
662 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663};
664
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
666 KeyEvent event;
667
668 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800669 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
670 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000671 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600672 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800673 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000674 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000675 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676 << "Should reject key events with undefined action.";
677
678 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800679 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
680 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600681 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800682 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000683 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000684 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685 << "Should reject key events with ACTION_MULTIPLE.";
686}
687
688TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
689 MotionEvent event;
690 PointerProperties pointerProperties[MAX_POINTERS + 1];
691 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800692 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800693 pointerProperties[i].clear();
694 pointerProperties[i].id = i;
695 pointerCoords[i].clear();
696 }
697
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800698 // Some constants commonly used below
699 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
700 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
701 constexpr int32_t metaState = AMETA_NONE;
702 constexpr MotionClassification classification = MotionClassification::NONE;
703
chaviw9eaa22c2020-07-01 16:21:27 -0700704 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800706 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000707 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700708 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700709 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
710 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000711 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800712 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000713 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000714 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715 << "Should reject motion events with undefined action.";
716
717 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800718 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800719 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
720 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
721 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
722 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000723 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000725 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject motion events with pointer down index too large.";
728
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700730 AMOTION_EVENT_ACTION_POINTER_DOWN |
731 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700732 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
733 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700734 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000735 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000737 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000738 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800739 << "Should reject motion events with pointer down index too small.";
740
741 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800742 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800743 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
744 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
745 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
746 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000747 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800748 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000749 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000750 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800751 << "Should reject motion events with pointer up index too large.";
752
Garfield Tanfbe732e2020-01-24 11:26:14 -0800753 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700754 AMOTION_EVENT_ACTION_POINTER_UP |
755 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700756 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
757 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700758 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000759 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000761 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000762 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763 << "Should reject motion events with pointer up index too small.";
764
765 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800766 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
767 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700768 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700769 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
770 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000771 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800772 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000773 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000774 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800775 << "Should reject motion events with 0 pointers.";
776
Garfield Tanfbe732e2020-01-24 11:26:14 -0800777 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
778 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700779 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
781 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000782 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with more than MAX_POINTERS pointers.";
787
788 // Rejects motion events with invalid pointer ids.
789 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800790 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
791 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700792 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700793 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
794 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000795 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800796 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000797 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000798 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800799 << "Should reject motion events with pointer ids less than 0.";
800
801 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800802 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
803 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700804 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700805 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
806 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000807 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800808 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000809 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000810 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800811 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
812
813 // Rejects motion events with duplicate pointer ids.
814 pointerProperties[0].id = 1;
815 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with duplicate pointer ids.";
826}
827
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800828/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
829
830TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
831 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000832 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800833 ASSERT_TRUE(mDispatcher->waitForIdle());
834
835 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
836}
837
838TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000839 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
840 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000841 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842
843 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
844 args.policyFlags |= POLICY_FLAG_TRUSTED;
845 mFakePolicy->assertNotifySwitchWasCalled(args);
846}
847
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700848namespace {
849
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700850static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700851// Default input dispatching timeout if there is no focused application or paused window
852// from which to determine an appropriate dispatching timeout.
853static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
854 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
855 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800856
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800857class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800858public:
Garfield Tan15601662020-09-22 15:32:38 -0700859 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700860 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800861
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000862 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700863 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700864 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 if (!consumeSeq) {
866 return nullptr;
867 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000868 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700869 return event;
870 }
871
872 /**
873 * Receive an event without acknowledging it.
874 * Return the sequence number that could later be used to send finished signal.
875 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700876 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
877 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800878 uint32_t consumeSeq;
879 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800880
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800881 std::chrono::time_point start = std::chrono::steady_clock::now();
882 status_t status = WOULD_BLOCK;
883 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700884 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
885 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700887 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 break;
889 }
890 }
891
892 if (status == WOULD_BLOCK) {
893 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700894 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800895 }
896
897 if (status != OK) {
898 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700899 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800900 }
901 if (event == nullptr) {
902 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700903 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800904 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 if (outEvent != nullptr) {
906 *outEvent = event;
907 }
908 return consumeSeq;
909 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800910
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700911 /**
912 * To be used together with "receiveEvent" to complete the consumption of an event.
913 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000914 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700915 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800917 }
918
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000919 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700920 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000921 ASSERT_EQ(OK, status);
922 }
923
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700924 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000925 std::optional<int32_t> expectedDisplayId,
926 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700927 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928
929 ASSERT_NE(nullptr, event) << mName.c_str()
930 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800931 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700932 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
933 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800934
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000935 if (expectedDisplayId.has_value()) {
936 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
937 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800938
Tiger Huang8664f8c2018-10-11 19:14:35 +0800939 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700940 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800941 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700942 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000943 if (expectedFlags.has_value()) {
944 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
945 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800946 break;
947 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700948 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800949 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700950 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000951 if (expectedFlags.has_value()) {
952 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
953 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800954 break;
955 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700956 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100957 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
958 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700959 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800960 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
961 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700962 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000963 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
964 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800966 FAIL() << "Use 'consumeDragEvent' for DRAG events";
967 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800968 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800969 }
970
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800971 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700972 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800973
974 if (event == nullptr) {
975 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
976 return nullptr;
977 }
978
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700979 if (event->getType() != InputEventType::MOTION) {
980 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800981 return nullptr;
982 }
983 return static_cast<MotionEvent*>(event);
984 }
985
986 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
987 MotionEvent* motionEvent = consumeMotion();
988 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
989 ASSERT_THAT(*motionEvent, matcher);
990 }
991
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100992 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700993 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 ASSERT_NE(nullptr, event) << mName.c_str()
995 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 ASSERT_EQ(InputEventType::FOCUS, event->getType())
997 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100998
999 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1000 << mName.c_str() << ": event displayId should always be NONE.";
1001
1002 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1003 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001004 }
1005
Prabir Pradhan99987712020-11-10 18:43:05 -08001006 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001007 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 ASSERT_NE(nullptr, event) << mName.c_str()
1009 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1011 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001012
1013 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1014 << mName.c_str() << ": event displayId should always be NONE.";
1015
1016 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1017 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1018 }
1019
arthurhungb89ccb02020-12-30 16:19:01 +08001020 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001021 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001022 ASSERT_NE(nullptr, event) << mName.c_str()
1023 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001024 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001025
1026 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1027 << mName.c_str() << ": event displayId should always be NONE.";
1028
1029 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1030 EXPECT_EQ(isExiting, dragEvent.isExiting());
1031 EXPECT_EQ(x, dragEvent.getX());
1032 EXPECT_EQ(y, dragEvent.getY());
1033 }
1034
Antonio Kantekf16f2832021-09-28 04:39:20 +00001035 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001036 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001037 ASSERT_NE(nullptr, event) << mName.c_str()
1038 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001039 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1040 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001041
1042 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1043 << mName.c_str() << ": event displayId should always be NONE.";
1044 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1045 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1046 }
1047
chaviwd1c23182019-12-20 18:44:56 -08001048 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001049 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001050 if (event == nullptr) {
1051 return;
1052 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001053 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001054 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001055 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001056 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001057 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001058 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001059 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001060 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1061 ADD_FAILURE() << "Received focus event, hasFocus = "
1062 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001063 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001064 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1065 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1066 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001067 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001068 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1069 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1070 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001071 }
1072 FAIL() << mName.c_str()
1073 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001074 }
1075
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001076 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080private:
1081 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001082 PreallocatedInputEventFactory mEventFactory;
1083
1084 std::string mName;
1085};
1086
chaviw3277faf2021-05-19 16:45:23 -05001087class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001088public:
1089 static const int32_t WIDTH = 600;
1090 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001091
Chris Yea209fde2020-07-22 13:54:51 -07001092 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001093 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001094 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001095 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001097 base::Result<std::unique_ptr<InputChannel>> channel =
1098 dispatcher->createInputChannel(name);
1099 token = (*channel)->getConnectionToken();
1100 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001101 }
1102
1103 inputApplicationHandle->updateInfo();
1104 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1105
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001106 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001107 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001108 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001109 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001110 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001111 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001112 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001113 mInfo.globalScaleFactor = 1.0;
1114 mInfo.touchableRegion.clear();
1115 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001116 mInfo.ownerPid = WINDOW_PID;
1117 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001118 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001119 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001120 }
1121
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001122 sp<FakeWindowHandle> clone(int32_t displayId) {
1123 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1124 handle->mInfo = mInfo;
1125 handle->mInfo.displayId = displayId;
1126 handle->mInfo.id = sId++;
1127 handle->mInputReceiver = mInputReceiver;
1128 return handle;
1129 }
1130
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001131 void setTouchable(bool touchable) {
1132 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1133 }
chaviwd1c23182019-12-20 18:44:56 -08001134
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001135 void setFocusable(bool focusable) {
1136 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1137 }
1138
1139 void setVisible(bool visible) {
1140 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1141 }
Vishnu Nair958da932020-08-21 17:12:37 -07001142
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001143 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 }
1146
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001147 void setPaused(bool paused) {
1148 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1149 }
1150
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001151 void setPreventSplitting(bool preventSplitting) {
1152 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001153 }
1154
1155 void setSlippery(bool slippery) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1157 }
1158
1159 void setWatchOutsideTouch(bool watchOutside) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1161 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001162
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001163 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1164
1165 void setInterceptsStylus(bool interceptsStylus) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1167 }
1168
1169 void setDropInput(bool dropInput) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1171 }
1172
1173 void setDropInputIfObscured(bool dropInputIfObscured) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1175 }
1176
1177 void setNoInputChannel(bool noInputChannel) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1179 }
1180
Josep del Riob3981622023-04-18 15:49:45 +00001181 void setDisableUserActivity(bool disableUserActivity) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1183 }
1184
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001185 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1186
chaviw3277faf2021-05-19 16:45:23 -05001187 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001188
Bernardo Rufino7393d172021-02-26 13:56:11 +00001189 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1190
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001191 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001192 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001193 mInfo.touchableRegion.clear();
1194 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001195
1196 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1197 ui::Transform translate;
1198 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1199 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001200 }
1201
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001202 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1203
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001204 void setIsWallpaper(bool isWallpaper) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1206 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001207
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001208 void setDupTouchToWallpaper(bool hasWallpaper) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1210 }
chaviwd1c23182019-12-20 18:44:56 -08001211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setTrustedOverlay(bool trustedOverlay) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1214 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001215
chaviw9eaa22c2020-07-01 16:21:27 -07001216 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1217 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1218 }
1219
1220 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001221
yunho.shinf4a80b82020-11-16 21:13:57 +09001222 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1223
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001224 KeyEvent* consumeKey(bool handled = true) {
1225 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001226 if (event == nullptr) {
1227 ADD_FAILURE() << "Consume failed : no event";
1228 return nullptr;
1229 }
1230 if (event->getType() != InputEventType::KEY) {
1231 ADD_FAILURE() << "Instead of key event, got " << *event;
1232 return nullptr;
1233 }
1234 return static_cast<KeyEvent*>(event);
1235 }
1236
1237 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1238 KeyEvent* keyEvent = consumeKey();
1239 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1240 ASSERT_THAT(*keyEvent, matcher);
1241 }
1242
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001243 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001244 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 }
1246
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001247 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001248 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001249 }
1250
Svet Ganov5d3bc372020-01-26 23:11:07 -08001251 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001252 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001253 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1254 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 }
1256
1257 void consumeMotionMove(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(AMOTION_EVENT_ACTION_MOVE),
1260 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 }
1262
1263 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001265 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1266 }
1267
1268 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1269 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001270 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001271 expectedFlags);
1272 }
1273
Svet Ganov5d3bc372020-01-26 23:11:07 -08001274 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001275 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1276 int32_t expectedFlags = 0) {
1277 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1278 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 }
1281
1282 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedFlags = 0) {
1284 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1285 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001286 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001287 }
1288
1289 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001290 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001291 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001292 expectedFlags);
1293 }
1294
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001295 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1296 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001297 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001298 expectedFlags);
1299 }
1300
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001301 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1302 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001303 MotionEvent* motionEvent = consumeMotion();
1304 ASSERT_NE(nullptr, motionEvent);
1305 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1306 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1307 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001308 }
1309
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001310 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1311 ASSERT_NE(mInputReceiver, nullptr)
1312 << "Cannot consume events from a window with no receiver";
1313 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1314 }
1315
Prabir Pradhan99987712020-11-10 18:43:05 -08001316 void consumeCaptureEvent(bool hasCapture) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeCaptureEvent(hasCapture);
1320 }
1321
Prabir Pradhan5893d362023-11-17 04:30:40 +00001322 const MotionEvent& consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001323 MotionEvent* motionEvent = consumeMotion();
Prabir Pradhan5893d362023-11-17 04:30:40 +00001324 if (nullptr == motionEvent) {
1325 LOG(FATAL) << "Did not get a motion event, but expected " << matcher;
1326 }
1327 EXPECT_THAT(*motionEvent, matcher);
1328 return *motionEvent;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001329 }
1330
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001331 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001332 std::optional<int32_t> expectedDisplayId,
1333 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001334 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1335 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1336 expectedFlags);
1337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001354 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001367 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = true) {
chaviwaf87b3e2019-10-01 16:59:28 -07001368 if (mInputReceiver == nullptr) {
1369 return nullptr;
1370 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001371 return mInputReceiver->consume(timeout, handled);
chaviwaf87b3e2019-10-01 16:59:28 -07001372 }
1373
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001374 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001375 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001376 if (event == nullptr) {
1377 ADD_FAILURE() << "Consume failed : no event";
1378 return nullptr;
1379 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001380 if (event->getType() != InputEventType::MOTION) {
1381 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001382 return nullptr;
1383 }
1384 return static_cast<MotionEvent*>(event);
1385 }
1386
Arthur Hungb92218b2018-08-14 12:00:21 +08001387 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001388 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001389 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001390 return; // Can't receive events if the window does not have input channel
1391 }
1392 ASSERT_NE(nullptr, mInputReceiver)
1393 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001394 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001395 }
1396
chaviwaf87b3e2019-10-01 16:59:28 -07001397 sp<IBinder> getToken() { return mInfo.token; }
1398
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001399 const std::string& getName() { return mName; }
1400
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001401 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001402 mInfo.ownerPid = ownerPid;
1403 mInfo.ownerUid = ownerUid;
1404 }
1405
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001406 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001407
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001408 void destroyReceiver() { mInputReceiver = nullptr; }
1409
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001410 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1411
chaviwd1c23182019-12-20 18:44:56 -08001412private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001413 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001414 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001415 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001416 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001417 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001418};
1419
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001420std::atomic<int32_t> FakeWindowHandle::sId{1};
1421
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001422class FakeMonitorReceiver {
1423public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001424 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1425 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001426
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001427 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001428
1429 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001430 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1431 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001432 }
1433
1434 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001435 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
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 Vishniakou2defec02023-06-08 17:24:44 -07001473 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.
Harry Cutts33476232023-01-30 19:57:29 +00001582 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001583 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1584 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.
1593 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001594 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001595 currentTime);
1596
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.
1604 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001605 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001606 AMETA_NONE, currentTime);
1607
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.
Harry Cutts33476232023-01-30 19:57:29 +00001634 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001635 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1636 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) {
Harry Cutts33476232023-01-30 19:57:29 +00001655 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001656}
1657
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001658} // namespace
1659
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001660/**
1661 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1662 * broken channel.
1663 */
1664TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1666 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001667 sp<FakeWindowHandle>::make(application, mDispatcher,
1668 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001669
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001671
1672 // Window closes its channel, but the window remains.
1673 window->destroyReceiver();
1674 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1675}
1676
Arthur Hungb92218b2018-08-14 12:00:21 +08001677TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001678 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001679 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1680 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001681
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001682 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001684 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001686
1687 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001688 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001689}
1690
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001691TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001693 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1694 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001695
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001696 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001697 // Inject a MotionEvent to an unknown display.
1698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001699 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1701
1702 // Window should receive motion event.
1703 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1704}
1705
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001707 * Calling onWindowInfosChanged once should not cause any issues.
1708 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001709 * called twice.
1710 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001711TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1714 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001719 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001720 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001722
1723 // Window should receive motion event.
1724 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1725}
1726
1727/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001728 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001729 */
1730TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1733 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001734 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001735
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001740 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001742
1743 // Window should receive motion event.
1744 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1745}
1746
Arthur Hungb92218b2018-08-14 12:00:21 +08001747// The foreground window should receive the first touch down event.
1748TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001750 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001751 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001752 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001753 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001755 mDispatcher->onWindowInfosChanged(
1756 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001760
1761 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001762 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001763 windowSecond->assertNoEvents();
1764}
1765
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001766/**
1767 * Two windows: A top window, and a wallpaper behind the window.
1768 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1769 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001770 * 1. foregroundWindow <-- dup touch to wallpaper
1771 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001772 */
1773TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1775 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001776 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001777 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001778 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001779 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001780 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001782 mDispatcher->onWindowInfosChanged(
1783 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001785 injectMotionEvent(*mDispatcher,
1786 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1787 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1788 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1790
1791 // Both foreground window and its wallpaper should receive the touch down
1792 foregroundWindow->consumeMotionDown();
1793 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1794
1795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001796 injectMotionEvent(*mDispatcher,
1797 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1798 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1799 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1801
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001802 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001803 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1804
1805 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001806 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001807 foregroundWindow->consumeMotionCancel();
1808 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1809 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1810}
1811
1812/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001813 * Two fingers down on the window, and lift off the first finger.
1814 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1815 * contains a single pointer.
1816 */
1817TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1819 sp<FakeWindowHandle> window =
1820 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1821
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001822 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001823 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1825 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1826 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001827 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001828 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1829 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1830 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1831 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001832 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001833 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1834 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1835 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1836 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001837 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1838 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1839 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1840
1841 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001843 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1844 window->consumeMotionEvent(
1845 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1846}
1847
1848/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001849 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1850 * with the following differences:
1851 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1852 * clean up the connection.
1853 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1854 * Ensure that there's no crash in the dispatcher.
1855 */
1856TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1858 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001859 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001860 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001861 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001863 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001865 mDispatcher->onWindowInfosChanged(
1866 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001868 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001869 {100, 200}))
1870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1871
1872 // Both foreground window and its wallpaper should receive the touch down
1873 foregroundWindow->consumeMotionDown();
1874 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1875
1876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001877 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001878 ADISPLAY_ID_DEFAULT, {110, 200}))
1879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1880
1881 foregroundWindow->consumeMotionMove();
1882 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1883
1884 // Wallpaper closes its channel, but the window remains.
1885 wallpaperWindow->destroyReceiver();
1886 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1887
1888 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1889 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001890 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001891 foregroundWindow->consumeMotionCancel();
1892}
1893
Arthur Hungc539dbb2022-12-08 07:45:36 +00001894class ShouldSplitTouchFixture : public InputDispatcherTest,
1895 public ::testing::WithParamInterface<bool> {};
1896INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1897 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001898/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899 * A single window that receives touch (on top), and a wallpaper window underneath it.
1900 * The top window gets a multitouch gesture.
1901 * Ensure that wallpaper gets the same gesture.
1902 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001903TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001905 sp<FakeWindowHandle> foregroundWindow =
1906 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1907 foregroundWindow->setDupTouchToWallpaper(true);
1908 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909
1910 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001911 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001912 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001914 mDispatcher->onWindowInfosChanged(
1915 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916
1917 // Touch down on top window
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001920 {100, 100}))
1921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1922
1923 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001924 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1926
1927 // Second finger down on the top window
1928 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001929 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933 .build();
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 InputEventInjectionSync::WAIT_FOR_RESULT))
1937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1938
Harry Cutts33476232023-01-30 19:57:29 +00001939 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1940 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001942
1943 const MotionEvent secondFingerUpEvent =
1944 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1945 .displayId(ADISPLAY_ID_DEFAULT)
1946 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001947 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1948 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001949 .build();
1950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001951 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001952 InputEventInjectionSync::WAIT_FOR_RESULT))
1953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1954 foregroundWindow->consumeMotionPointerUp(0);
1955 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1956
1957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001958 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001959 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1960 AINPUT_SOURCE_TOUCHSCREEN)
1961 .displayId(ADISPLAY_ID_DEFAULT)
1962 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001963 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001964 .x(100)
1965 .y(100))
1966 .build(),
1967 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1969 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1970 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001971}
1972
1973/**
1974 * Two windows: a window on the left and window on the right.
1975 * A third window, wallpaper, is behind both windows, and spans both top windows.
1976 * The first touch down goes to the left window. A second pointer touches down on the right window.
1977 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1978 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1979 * ACTION_POINTER_DOWN(1).
1980 */
1981TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1983 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001984 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001986 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987
1988 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001989 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001991 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001992
1993 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001994 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001996 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001998 mDispatcher->onWindowInfosChanged(
1999 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2000 {},
2001 0,
2002 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003
2004 // Touch down on left window
2005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002006 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007 {100, 100}))
2008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2009
2010 // Both foreground window and its wallpaper should receive the touch down
2011 leftWindow->consumeMotionDown();
2012 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2013
2014 // Second finger down on the right window
2015 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002016 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002018 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2019 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020 .build();
2021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002022 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 InputEventInjectionSync::WAIT_FOR_RESULT))
2024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2025
2026 leftWindow->consumeMotionMove();
2027 // Since the touch is split, right window gets ACTION_DOWN
2028 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002029 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 expectedWallpaperFlags);
2031
2032 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002033 mDispatcher->onWindowInfosChanged(
2034 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035 leftWindow->consumeMotionCancel();
2036 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2037 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2038
2039 // The pointer that's still down on the right window moves, and goes to the right window only.
2040 // As far as the dispatcher's concerned though, both pointers are still present.
2041 const MotionEvent secondFingerMoveEvent =
2042 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2043 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002044 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2045 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046 .build();
2047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002048 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 InputEventInjectionSync::WAIT_FOR_RESULT));
2050 rightWindow->consumeMotionMove();
2051
2052 leftWindow->assertNoEvents();
2053 rightWindow->assertNoEvents();
2054 wallpaperWindow->assertNoEvents();
2055}
2056
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057/**
2058 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2059 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2060 * The right window should receive ACTION_DOWN.
2061 */
2062TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002063 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002064 sp<FakeWindowHandle> leftWindow =
2065 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2066 leftWindow->setFrame(Rect(0, 0, 200, 200));
2067 leftWindow->setDupTouchToWallpaper(true);
2068 leftWindow->setSlippery(true);
2069
2070 sp<FakeWindowHandle> rightWindow =
2071 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2072 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002073
2074 sp<FakeWindowHandle> wallpaperWindow =
2075 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2076 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002077
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002078 mDispatcher->onWindowInfosChanged(
2079 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2080 {},
2081 0,
2082 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002083
Arthur Hungc539dbb2022-12-08 07:45:36 +00002084 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002086 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002087 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089
2090 // Both foreground window and its wallpaper should receive the touch down
2091 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002092 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2093
Arthur Hungc539dbb2022-12-08 07:45:36 +00002094 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002096 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002097 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2099
Arthur Hungc539dbb2022-12-08 07:45:36 +00002100 leftWindow->consumeMotionCancel();
2101 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2102 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002103}
2104
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002105/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2107 * interactive, it might stop sending this flag.
2108 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2109 * to have a consistent input stream.
2110 *
2111 * Test procedure:
2112 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2113 * DOWN (new gesture).
2114 *
2115 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2116 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2117 *
2118 * We technically just need a single window here, but we are using two windows (spy on top and a
2119 * regular window below) to emulate the actual situation where it happens on the device.
2120 */
2121TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2123 sp<FakeWindowHandle> spyWindow =
2124 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2125 spyWindow->setFrame(Rect(0, 0, 200, 200));
2126 spyWindow->setTrustedOverlay(true);
2127 spyWindow->setSpy(true);
2128
2129 sp<FakeWindowHandle> window =
2130 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2131 window->setFrame(Rect(0, 0, 200, 200));
2132
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002133 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135
2136 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002137 mDispatcher->notifyMotion(
2138 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2139 .deviceId(touchDeviceId)
2140 .policyFlags(DEFAULT_POLICY_FLAGS)
2141 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2142 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002143
Prabir Pradhan678438e2023-04-13 19:32:51 +00002144 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2145 .deviceId(touchDeviceId)
2146 .policyFlags(DEFAULT_POLICY_FLAGS)
2147 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2148 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2149 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002150 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2151 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2152 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2153 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2154
2155 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002156 mDispatcher->notifyMotion(
2157 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2158 .deviceId(touchDeviceId)
2159 .policyFlags(0)
2160 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2161 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2162 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002163 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2164 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2165
2166 // We don't need to reset the device to reproduce the issue, but the reset event typically
2167 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002168 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002169
2170 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002171 mDispatcher->notifyMotion(
2172 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2173 .deviceId(touchDeviceId)
2174 .policyFlags(DEFAULT_POLICY_FLAGS)
2175 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2176 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002177 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2178 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2179
2180 // No more events
2181 spyWindow->assertNoEvents();
2182 window->assertNoEvents();
2183}
2184
2185/**
Linnan Li907ae732023-09-05 17:14:21 +08002186 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2187 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2188 * interactive, it might stop sending this flag.
2189 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2190 * the consistency of the hover event in this case.
2191 *
2192 * Test procedure:
2193 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2194 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2195 *
2196 * We expect to receive two full streams of hover events.
2197 */
2198TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2199 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2200
2201 sp<FakeWindowHandle> window =
2202 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2203 window->setFrame(Rect(0, 0, 300, 300));
2204
2205 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2206
2207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2208 .policyFlags(DEFAULT_POLICY_FLAGS)
2209 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2210 .build());
2211 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2212
2213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2214 .policyFlags(DEFAULT_POLICY_FLAGS)
2215 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2216 .build());
2217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2218
2219 // Send hover exit without the default policy flags.
2220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2221 .policyFlags(0)
2222 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2223 .build());
2224
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2226
2227 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2228 // right event.
2229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2230 .policyFlags(DEFAULT_POLICY_FLAGS)
2231 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2232 .build());
2233 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2234
2235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2236 .policyFlags(DEFAULT_POLICY_FLAGS)
2237 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2238 .build());
2239 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2240
2241 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2242 .policyFlags(DEFAULT_POLICY_FLAGS)
2243 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2244 .build());
2245 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2246}
2247
2248/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002249 * Two windows: a window on the left and a window on the right.
2250 * Mouse is hovered from the right window into the left window.
2251 * Next, we tap on the left window, where the cursor was last seen.
2252 * The second tap is done onto the right window.
2253 * The mouse and tap are from two different devices.
2254 * We technically don't need to set the downtime / eventtime for these events, but setting these
2255 * explicitly helps during debugging.
2256 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2257 * In the buggy implementation, a tap on the right window would cause a crash.
2258 */
2259TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2261 sp<FakeWindowHandle> leftWindow =
2262 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2263 leftWindow->setFrame(Rect(0, 0, 200, 200));
2264
2265 sp<FakeWindowHandle> rightWindow =
2266 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2267 rightWindow->setFrame(Rect(200, 0, 400, 200));
2268
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002269 mDispatcher->onWindowInfosChanged(
2270 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2272 // stale.
2273 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2274 const int32_t mouseDeviceId = 6;
2275 const int32_t touchDeviceId = 4;
2276 // Move the cursor from right
2277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002278 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002279 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2280 AINPUT_SOURCE_MOUSE)
2281 .deviceId(mouseDeviceId)
2282 .downTime(baseTime + 10)
2283 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002284 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002285 .build()));
2286 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2287
2288 // .. to the left window
2289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002290 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002291 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2292 AINPUT_SOURCE_MOUSE)
2293 .deviceId(mouseDeviceId)
2294 .downTime(baseTime + 10)
2295 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002296 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002297 .build()));
2298 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2299 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2300 // Now tap the left window
2301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002302 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002303 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2304 AINPUT_SOURCE_TOUCHSCREEN)
2305 .deviceId(touchDeviceId)
2306 .downTime(baseTime + 40)
2307 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002308 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002309 .build()));
2310 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2311 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2312
2313 // release tap
2314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002315 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002316 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2317 AINPUT_SOURCE_TOUCHSCREEN)
2318 .deviceId(touchDeviceId)
2319 .downTime(baseTime + 40)
2320 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002321 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002322 .build()));
2323 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2324
2325 // Tap the window on the right
2326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002327 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002328 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2329 AINPUT_SOURCE_TOUCHSCREEN)
2330 .deviceId(touchDeviceId)
2331 .downTime(baseTime + 60)
2332 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002333 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002334 .build()));
2335 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2336
2337 // release tap
2338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002340 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2341 AINPUT_SOURCE_TOUCHSCREEN)
2342 .deviceId(touchDeviceId)
2343 .downTime(baseTime + 60)
2344 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002345 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002346 .build()));
2347 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2348
2349 // No more events
2350 leftWindow->assertNoEvents();
2351 rightWindow->assertNoEvents();
2352}
2353
2354/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002355 * Start hovering in a window. While this hover is still active, make another window appear on top.
2356 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2357 * While the top window is present, the hovering is stopped.
2358 * Later, hovering gets resumed again.
2359 * Ensure that new hover gesture is handled correctly.
2360 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2361 * to the window that's currently being hovered over.
2362 */
2363TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2365 sp<FakeWindowHandle> window =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2367 window->setFrame(Rect(0, 0, 200, 200));
2368
2369 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002370 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002371
2372 // Start hovering in the window
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2374 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2375 .build());
2376 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2377
2378 // Now, an obscuring window appears!
2379 sp<FakeWindowHandle> obscuringWindow =
2380 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2381 ADISPLAY_ID_DEFAULT,
2382 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2383 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2384 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2385 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2386 obscuringWindow->setNoInputChannel(true);
2387 obscuringWindow->setFocusable(false);
2388 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002389 mDispatcher->onWindowInfosChanged(
2390 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002391
2392 // While this new obscuring window is present, the hovering is stopped
2393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2394 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2395 .build());
2396 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2397
2398 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002399 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002400
2401 // And a new hover gesture starts.
2402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2403 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2404 .build());
2405 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2406}
2407
2408/**
2409 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2410 * the obscuring window.
2411 */
2412TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2414 sp<FakeWindowHandle> window =
2415 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2416 window->setFrame(Rect(0, 0, 200, 200));
2417
2418 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002419 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002420
2421 // Start hovering in the window
2422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2424 .build());
2425 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2426
2427 // Now, an obscuring window appears!
2428 sp<FakeWindowHandle> obscuringWindow =
2429 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2430 ADISPLAY_ID_DEFAULT,
2431 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2432 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2433 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2434 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2435 obscuringWindow->setNoInputChannel(true);
2436 obscuringWindow->setFocusable(false);
2437 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002438 mDispatcher->onWindowInfosChanged(
2439 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002440
2441 // While this new obscuring window is present, the hovering continues. The event can't go to the
2442 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2443 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2444 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2445 .build());
2446 obscuringWindow->assertNoEvents();
2447 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2448
2449 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002450 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002451
2452 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2453 // so it should generate a HOVER_ENTER
2454 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2455 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2456 .build());
2457 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2458
2459 // Now the MOVE should be getting dispatched normally
2460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2461 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2462 .build());
2463 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2464}
2465
2466/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002467 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2468 * events are delivered to the window.
2469 */
2470TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2472 sp<FakeWindowHandle> window =
2473 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2474 window->setFrame(Rect(0, 0, 200, 200));
2475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2476
2477 // Start hovering in the window
2478 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2479 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2480 .build());
2481 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2482
2483 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2484 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2485 .build());
2486 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2487
2488 // Scroll with the mouse
2489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2490 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2491 .build());
2492 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2493}
2494
2495using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2496
2497/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002498 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2499 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002500 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002501TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002502 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2503 sp<FakeWindowHandle> window =
2504 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2505 window->setFrame(Rect(0, 0, 200, 200));
2506
2507 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2508
2509 constexpr int32_t touchDeviceId = 4;
2510 constexpr int32_t stylusDeviceId = 2;
2511
2512 // Stylus down
2513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2514 .deviceId(stylusDeviceId)
2515 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2516 .build());
2517 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2518
2519 // Touch down
2520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2521 .deviceId(touchDeviceId)
2522 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2523 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002524
2525 // Touch move
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2527 .deviceId(touchDeviceId)
2528 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2529 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002530 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002531
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002532 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2534 .deviceId(stylusDeviceId)
2535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2536 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002537 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2538 WithCoords(101, 111)));
2539
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002540 window->assertNoEvents();
2541}
2542
2543/**
2544 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002545 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002546 * Similar test as above, but with added SPY window.
2547 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002548TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2550 sp<FakeWindowHandle> window =
2551 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2552 sp<FakeWindowHandle> spyWindow =
2553 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2554 spyWindow->setFrame(Rect(0, 0, 200, 200));
2555 spyWindow->setTrustedOverlay(true);
2556 spyWindow->setSpy(true);
2557 window->setFrame(Rect(0, 0, 200, 200));
2558
2559 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2560
2561 constexpr int32_t touchDeviceId = 4;
2562 constexpr int32_t stylusDeviceId = 2;
2563
2564 // Stylus down
2565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2566 .deviceId(stylusDeviceId)
2567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2568 .build());
2569 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2570 spyWindow->consumeMotionEvent(
2571 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2572
2573 // Touch down
2574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2575 .deviceId(touchDeviceId)
2576 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2577 .build());
2578
2579 // Touch move
2580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2581 .deviceId(touchDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2583 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002584
2585 // Touch is ignored because stylus is already down
2586
2587 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2589 .deviceId(stylusDeviceId)
2590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2591 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002592 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2593 WithCoords(101, 111)));
2594 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2595 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002596
2597 window->assertNoEvents();
2598 spyWindow->assertNoEvents();
2599}
2600
2601/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002602 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002603 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002604 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002605TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2607 sp<FakeWindowHandle> window =
2608 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2609 window->setFrame(Rect(0, 0, 200, 200));
2610
2611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2612
2613 constexpr int32_t touchDeviceId = 4;
2614 constexpr int32_t stylusDeviceId = 2;
2615
2616 // Stylus down on the window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2618 .deviceId(stylusDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2620 .build());
2621 window->consumeMotionEvent(
2622 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2623
2624 // Touch down on window
2625 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2626 .deviceId(touchDeviceId)
2627 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2628 .build());
2629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2630 .deviceId(touchDeviceId)
2631 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2632 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002633
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002634 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002635
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002636 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2638 .deviceId(stylusDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2640 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002641 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2642 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002644 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2646 .deviceId(touchDeviceId)
2647 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2648 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002649 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002650}
2651
2652/**
2653 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002654 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002655 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002656TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2658 sp<FakeWindowHandle> window =
2659 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2660 window->setFrame(Rect(0, 0, 200, 200));
2661
2662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2663
2664 constexpr int32_t touchDeviceId = 4;
2665 constexpr int32_t stylusDeviceId = 2;
2666
2667 // Touch down on window
2668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2669 .deviceId(touchDeviceId)
2670 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2671 .build());
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2673 .deviceId(touchDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2675 .build());
2676 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2677 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2678
2679 // Stylus hover on the window
2680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2681 .deviceId(stylusDeviceId)
2682 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2683 .build());
2684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2685 .deviceId(stylusDeviceId)
2686 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2687 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002688 // Stylus hover movement causes touch to be canceled
2689 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2690 WithCoords(141, 146)));
2691 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2692 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2693 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2694 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002695
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002696 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002697 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2698 .deviceId(touchDeviceId)
2699 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2700 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002701
2702 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002703}
2704
2705/**
2706 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2707 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2708 * become active.
2709 */
2710TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2712 sp<FakeWindowHandle> window =
2713 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2714 window->setFrame(Rect(0, 0, 200, 200));
2715
2716 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2717
2718 constexpr int32_t stylusDeviceId1 = 3;
2719 constexpr int32_t stylusDeviceId2 = 5;
2720
2721 // Touch down on window
2722 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2723 .deviceId(stylusDeviceId1)
2724 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2725 .build());
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId1)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2729 .build());
2730 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2731 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2732
2733 // Second stylus down
2734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2735 .deviceId(stylusDeviceId2)
2736 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2737 .build());
2738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2739 .deviceId(stylusDeviceId2)
2740 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2741 .build());
2742
2743 // First stylus is canceled, second one takes over.
2744 window->consumeMotionEvent(
2745 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2746 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2747 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2748
2749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2750 .deviceId(stylusDeviceId1)
2751 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2752 .build());
2753 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002754 window->assertNoEvents();
2755}
2756
2757/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002758 * One window. Touch down on the window. Then, stylus down on the window from another device.
2759 * Ensure that is canceled, because stylus down should be preferred over touch.
2760 */
2761TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2763 sp<FakeWindowHandle> window =
2764 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2765 window->setFrame(Rect(0, 0, 200, 200));
2766
2767 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2768
2769 constexpr int32_t touchDeviceId = 4;
2770 constexpr int32_t stylusDeviceId = 2;
2771
2772 // Touch down on window
2773 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2774 .deviceId(touchDeviceId)
2775 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2776 .build());
2777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2778 .deviceId(touchDeviceId)
2779 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2780 .build());
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2783
2784 // Stylus down on the window
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2786 .deviceId(stylusDeviceId)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2791
2792 // Subsequent stylus movements are delivered correctly
2793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2794 .deviceId(stylusDeviceId)
2795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2796 .build());
2797 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2798 WithCoords(101, 111)));
2799}
2800
2801/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002802 * Two windows: a window on the left and a window on the right.
2803 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2804 * down. Then, on the left window, also place second touch pointer down.
2805 * This test tries to reproduce a crash.
2806 * In the buggy implementation, second pointer down on the left window would cause a crash.
2807 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002808TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2810 sp<FakeWindowHandle> leftWindow =
2811 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2812 leftWindow->setFrame(Rect(0, 0, 200, 200));
2813
2814 sp<FakeWindowHandle> rightWindow =
2815 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2816 rightWindow->setFrame(Rect(200, 0, 400, 200));
2817
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002818 mDispatcher->onWindowInfosChanged(
2819 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002820
2821 const int32_t touchDeviceId = 4;
2822 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002823
2824 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2826 .deviceId(mouseDeviceId)
2827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2828 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002829 leftWindow->consumeMotionEvent(
2830 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2831
2832 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2834 .deviceId(mouseDeviceId)
2835 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2836 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2837 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002838
2839 leftWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2841 leftWindow->consumeMotionEvent(
2842 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2843
Prabir Pradhan678438e2023-04-13 19:32:51 +00002844 mDispatcher->notifyMotion(
2845 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2846 .deviceId(mouseDeviceId)
2847 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2848 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2849 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2850 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002851 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2852
2853 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2855 .deviceId(touchDeviceId)
2856 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2857 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002858 leftWindow->assertNoEvents();
2859
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002860 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2861
2862 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002863 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2864 .deviceId(touchDeviceId)
2865 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2866 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2867 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002868 // Since this is now a new splittable pointer going down on the left window, and it's coming
2869 // from a different device, the current gesture in the left window (pointer down) should first
2870 // be canceled.
2871 leftWindow->consumeMotionEvent(
2872 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002873 leftWindow->consumeMotionEvent(
2874 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2875 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2876 // current implementation.
2877 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2878 rightWindow->consumeMotionEvent(
2879 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2880
2881 leftWindow->assertNoEvents();
2882 rightWindow->assertNoEvents();
2883}
2884
2885/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002886 * Two windows: a window on the left and a window on the right.
2887 * Mouse is hovered on the left window and stylus is hovered on the right window.
2888 */
2889TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2891 sp<FakeWindowHandle> leftWindow =
2892 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2893 leftWindow->setFrame(Rect(0, 0, 200, 200));
2894
2895 sp<FakeWindowHandle> rightWindow =
2896 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2897 rightWindow->setFrame(Rect(200, 0, 400, 200));
2898
2899 mDispatcher->onWindowInfosChanged(
2900 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2901
2902 const int32_t stylusDeviceId = 3;
2903 const int32_t mouseDeviceId = 6;
2904
2905 // Start hovering over the left window
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2907 .deviceId(mouseDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2909 .build());
2910 leftWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2912
2913 // Stylus hovered on right window
2914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2915 .deviceId(stylusDeviceId)
2916 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2917 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002918 rightWindow->consumeMotionEvent(
2919 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2920
2921 // Subsequent HOVER_MOVE events are dispatched correctly.
2922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2923 .deviceId(mouseDeviceId)
2924 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2925 .build());
2926 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002927 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002928
2929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2930 .deviceId(stylusDeviceId)
2931 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2932 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002934 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935
2936 leftWindow->assertNoEvents();
2937 rightWindow->assertNoEvents();
2938}
2939
2940/**
2941 * Three windows: a window on the left and a window on the right.
2942 * And a spy window that's positioned above all of them.
2943 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2944 * Check the stream that's received by the spy.
2945 */
2946TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2948
2949 sp<FakeWindowHandle> spyWindow =
2950 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2951 spyWindow->setFrame(Rect(0, 0, 400, 400));
2952 spyWindow->setTrustedOverlay(true);
2953 spyWindow->setSpy(true);
2954
2955 sp<FakeWindowHandle> leftWindow =
2956 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2957 leftWindow->setFrame(Rect(0, 0, 200, 200));
2958
2959 sp<FakeWindowHandle> rightWindow =
2960 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2961
2962 rightWindow->setFrame(Rect(200, 0, 400, 200));
2963
2964 mDispatcher->onWindowInfosChanged(
2965 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2966
2967 const int32_t stylusDeviceId = 1;
2968 const int32_t touchDeviceId = 2;
2969
2970 // Stylus down on the left window
2971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2972 .deviceId(stylusDeviceId)
2973 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2974 .build());
2975 leftWindow->consumeMotionEvent(
2976 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2977 spyWindow->consumeMotionEvent(
2978 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2979
2980 // Touch down on the right window
2981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2982 .deviceId(touchDeviceId)
2983 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2984 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002985 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986 rightWindow->consumeMotionEvent(
2987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002988
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002989 // Spy window does not receive touch events, because stylus events take precedence, and it
2990 // already has an active stylus gesture.
2991
2992 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2994 .deviceId(stylusDeviceId)
2995 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2996 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002997 leftWindow->consumeMotionEvent(
2998 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2999 spyWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003002 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3004 .deviceId(touchDeviceId)
3005 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3006 .build());
3007 rightWindow->consumeMotionEvent(
3008 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003009
3010 spyWindow->assertNoEvents();
3011 leftWindow->assertNoEvents();
3012 rightWindow->assertNoEvents();
3013}
3014
3015/**
3016 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3017 * both.
3018 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003019 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003020 * At the same time, left and right should be getting independent streams of hovering and touch,
3021 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003022 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003023TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3025
3026 sp<FakeWindowHandle> spyWindow =
3027 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3028 spyWindow->setFrame(Rect(0, 0, 400, 400));
3029 spyWindow->setTrustedOverlay(true);
3030 spyWindow->setSpy(true);
3031
3032 sp<FakeWindowHandle> leftWindow =
3033 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3034 leftWindow->setFrame(Rect(0, 0, 200, 200));
3035
3036 sp<FakeWindowHandle> rightWindow =
3037 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3038 rightWindow->setFrame(Rect(200, 0, 400, 200));
3039
3040 mDispatcher->onWindowInfosChanged(
3041 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3042
3043 const int32_t stylusDeviceId = 1;
3044 const int32_t touchDeviceId = 2;
3045
3046 // Stylus hover on the left window
3047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3048 .deviceId(stylusDeviceId)
3049 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3050 .build());
3051 leftWindow->consumeMotionEvent(
3052 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3053 spyWindow->consumeMotionEvent(
3054 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3055
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003056 // Touch down on the right window. Spy doesn't receive this touch because it already has
3057 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3059 .deviceId(touchDeviceId)
3060 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3061 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003062 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003063 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 rightWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3066
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003067 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3069 .deviceId(stylusDeviceId)
3070 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3071 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003072 leftWindow->consumeMotionEvent(
3073 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003074 spyWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003076
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3079 .deviceId(touchDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3081 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003082 rightWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3084
3085 spyWindow->assertNoEvents();
3086 leftWindow->assertNoEvents();
3087 rightWindow->assertNoEvents();
3088}
3089
3090/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091 * On a single window, use two different devices: mouse and touch.
3092 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3093 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3094 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3095 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3096 * represent a new gesture.
3097 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003098TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3100 sp<FakeWindowHandle> window =
3101 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3102 window->setFrame(Rect(0, 0, 400, 400));
3103
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003104 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003105
3106 const int32_t touchDeviceId = 4;
3107 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003109 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003110 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3111 .deviceId(touchDeviceId)
3112 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3113 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003115 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3116 .deviceId(touchDeviceId)
3117 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3118 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3119 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003121 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3122 .deviceId(touchDeviceId)
3123 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3124 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3125 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003126 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3127 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3128 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3129
3130 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3132 .deviceId(mouseDeviceId)
3133 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3134 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136
3137 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003138 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3140
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(
3142 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3143 .deviceId(mouseDeviceId)
3144 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3145 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3146 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3147 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003148 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3149
3150 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003151 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3152 .deviceId(touchDeviceId)
3153 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3154 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3155 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003156 // Since we already canceled this touch gesture, it will be ignored until a completely new
3157 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3158 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3159 // However, mouse movements should continue to work.
3160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3161 .deviceId(mouseDeviceId)
3162 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3163 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3164 .build());
3165 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3166
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003167 window->assertNoEvents();
3168}
3169
3170/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003171 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3172 * the injected event.
3173 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003174TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3176 sp<FakeWindowHandle> window =
3177 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3178 window->setFrame(Rect(0, 0, 400, 400));
3179
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003181
3182 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003183 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3184 // completion.
3185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003186 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003187 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3188 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003190 .build()));
3191 window->consumeMotionEvent(
3192 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3193
3194 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3195 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3197 .deviceId(touchDeviceId)
3198 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3199 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003200
3201 window->consumeMotionEvent(
3202 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3203 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3204}
3205
3206/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003207 * This test is similar to the test above, but the sequence of injected events is different.
3208 *
3209 * Two windows: a window on the left and a window on the right.
3210 * Mouse is hovered over the left window.
3211 * Next, we tap on the left window, where the cursor was last seen.
3212 *
3213 * After that, we inject one finger down onto the right window, and then a second finger down onto
3214 * the left window.
3215 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3216 * window (first), and then another on the left window (second).
3217 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3218 * In the buggy implementation, second finger down on the left window would cause a crash.
3219 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003220TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3222 sp<FakeWindowHandle> leftWindow =
3223 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3224 leftWindow->setFrame(Rect(0, 0, 200, 200));
3225
3226 sp<FakeWindowHandle> rightWindow =
3227 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3228 rightWindow->setFrame(Rect(200, 0, 400, 200));
3229
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003230 mDispatcher->onWindowInfosChanged(
3231 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003232
3233 const int32_t mouseDeviceId = 6;
3234 const int32_t touchDeviceId = 4;
3235 // Hover over the left window. Keep the cursor there.
3236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003237 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003238 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3239 AINPUT_SOURCE_MOUSE)
3240 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003241 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003242 .build()));
3243 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3244
3245 // Tap on left window
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003248 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252 .build()));
3253
3254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003255 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003256 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3257 AINPUT_SOURCE_TOUCHSCREEN)
3258 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003260 .build()));
3261 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3262 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3263 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3264
3265 // First finger down on right window
3266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003267 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3269 AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003271 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003272 .build()));
3273 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3274
3275 // Second finger down on the left window
3276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003277 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003278 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3279 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003280 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3281 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003282 .build()));
3283 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3284 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3285
3286 // No more events
3287 leftWindow->assertNoEvents();
3288 rightWindow->assertNoEvents();
3289}
3290
3291/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003292 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3293 * While the touch is down, new hover events from the stylus device should be ignored. After the
3294 * touch is gone, stylus hovering should start working again.
3295 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003296TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003297 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3298 sp<FakeWindowHandle> window =
3299 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3300 window->setFrame(Rect(0, 0, 200, 200));
3301
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003302 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003303
3304 const int32_t stylusDeviceId = 5;
3305 const int32_t touchDeviceId = 4;
3306 // Start hovering with stylus
3307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003309 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003310 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003311 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003313 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003314
3315 // Finger down on the window
3316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003317 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003318 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003320 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003321 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003322 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003323
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003324 // Continue hovering with stylus.
3325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003326 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003327 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3328 AINPUT_SOURCE_STYLUS)
3329 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003330 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003332 // Hovers continue to work
3333 window->consumeMotionEvent(
3334 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335
3336 // Lift up the finger
3337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003338 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3340 AINPUT_SOURCE_TOUCHSCREEN)
3341 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003342 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003344
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003346 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003347 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3348 AINPUT_SOURCE_STYLUS)
3349 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003350 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003351 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003352 window->consumeMotionEvent(
3353 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003354 window->assertNoEvents();
3355}
3356
3357/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003358 * A spy window above a window with no input channel.
3359 * Start hovering with a stylus device, and then tap with it.
3360 * Ensure spy window receives the entire sequence.
3361 */
3362TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3364 sp<FakeWindowHandle> spyWindow =
3365 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3366 spyWindow->setFrame(Rect(0, 0, 200, 200));
3367 spyWindow->setTrustedOverlay(true);
3368 spyWindow->setSpy(true);
3369 sp<FakeWindowHandle> window =
3370 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3371 window->setNoInputChannel(true);
3372 window->setFrame(Rect(0, 0, 200, 200));
3373
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003374 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003375
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003376 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003377 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3378 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3379 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003380 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3381 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3384 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003385 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3386
3387 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3389 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3390 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003391 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3392
3393 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3396 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003397 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3398
3399 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3402 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003403 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3404 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3406 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3407 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003408 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3409
3410 // No more events
3411 spyWindow->assertNoEvents();
3412 window->assertNoEvents();
3413}
3414
3415/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003416 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3417 * rejected. But since we already have an ongoing gesture, this event should be processed.
3418 * This prevents inconsistent events being handled inside the dispatcher.
3419 */
3420TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3422
3423 sp<FakeWindowHandle> window =
3424 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3425 window->setFrame(Rect(0, 0, 200, 200));
3426
3427 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3428
3429 // Start hovering with stylus
3430 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3431 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3432 .build());
3433 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3434
3435 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3436 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3437 .build();
3438 // Make this 'hoverExit' event stale
3439 mFakePolicy->setStaleEventTimeout(100ms);
3440 std::this_thread::sleep_for(100ms);
3441
3442 // It shouldn't be dropped by the dispatcher, even though it's stale.
3443 mDispatcher->notifyMotion(hoverExit);
3444 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3445
3446 // Stylus starts hovering again! There should be no crash.
3447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3448 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3449 .build());
3450 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3451}
3452
3453/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003454 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3455 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3456 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3457 * While the mouse is down, new move events from the touch device should be ignored.
3458 */
3459TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3461 sp<FakeWindowHandle> spyWindow =
3462 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3463 spyWindow->setFrame(Rect(0, 0, 200, 200));
3464 spyWindow->setTrustedOverlay(true);
3465 spyWindow->setSpy(true);
3466 sp<FakeWindowHandle> window =
3467 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3468 window->setFrame(Rect(0, 0, 200, 200));
3469
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003470 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003471
3472 const int32_t mouseDeviceId = 7;
3473 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003474
3475 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3477 .deviceId(mouseDeviceId)
3478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3479 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003480 spyWindow->consumeMotionEvent(
3481 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3482 window->consumeMotionEvent(
3483 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3484
3485 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3487 .deviceId(touchDeviceId)
3488 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3489 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003490 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3491 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3492 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3493 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3494
Prabir Pradhan678438e2023-04-13 19:32:51 +00003495 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3496 .deviceId(touchDeviceId)
3497 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3498 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003499 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3500 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3501
3502 // Pilfer the stream
3503 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3504 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3505
Prabir Pradhan678438e2023-04-13 19:32:51 +00003506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3507 .deviceId(touchDeviceId)
3508 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3509 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003510 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3511
3512 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3514 .deviceId(mouseDeviceId)
3515 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3516 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3517 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003518
3519 spyWindow->consumeMotionEvent(
3520 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3521 spyWindow->consumeMotionEvent(
3522 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3523 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3524
Prabir Pradhan678438e2023-04-13 19:32:51 +00003525 mDispatcher->notifyMotion(
3526 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3527 .deviceId(mouseDeviceId)
3528 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3529 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3530 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3531 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003532 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3533 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3534
3535 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3537 .deviceId(mouseDeviceId)
3538 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3539 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3540 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003541 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3542 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3543
3544 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3546 .deviceId(touchDeviceId)
3547 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3548 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003549
3550 // No more events
3551 spyWindow->assertNoEvents();
3552 window->assertNoEvents();
3553}
3554
3555/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003556 * On the display, have a single window, and also an area where there's no window.
3557 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3558 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3559 */
3560TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3562 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003563 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003564
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003565 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003566
3567 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003568 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003569
3570 mDispatcher->waitForIdle();
3571 window->assertNoEvents();
3572
3573 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003574 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003575 mDispatcher->waitForIdle();
3576 window->consumeMotionDown();
3577}
3578
3579/**
3580 * Same test as above, but instead of touching the empty space, the first touch goes to
3581 * non-touchable window.
3582 */
3583TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3585 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003586 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003587 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3588 window1->setTouchable(false);
3589 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003590 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003591 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3592
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003593 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003594
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003595 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003596 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003597
3598 mDispatcher->waitForIdle();
3599 window1->assertNoEvents();
3600 window2->assertNoEvents();
3601
3602 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003603 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003604 mDispatcher->waitForIdle();
3605 window2->consumeMotionDown();
3606}
3607
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003608/**
3609 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3610 * to the event time of the first ACTION_DOWN sent to the particular window.
3611 */
3612TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3613 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3614 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003615 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003616 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3617 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003618 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003619 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3620
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003621 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003623 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003624 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003625
3626 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003627
3628 MotionEvent* motionEvent1 = window1->consumeMotion();
3629 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003630 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003631 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3632 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003633
3634 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003635 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003636 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003637 MotionEvent* motionEvent2 = window2->consumeMotion();
3638 ASSERT_NE(motionEvent2, nullptr);
3639 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003640 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003641 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003642
3643 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003644 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003645 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003646 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003647
3648 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003650 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003651 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003652
3653 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3654 window1->consumeMotionMove();
3655 window1->assertNoEvents();
3656
3657 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003658 mDispatcher->notifyMotion(
3659 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003660 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003661 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003662
Prabir Pradhan678438e2023-04-13 19:32:51 +00003663 mDispatcher->notifyMotion(
3664 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003665 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003666 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003667}
3668
Garfield Tandf26e862020-07-01 20:18:19 -07003669TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003671 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003672 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003673 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003674 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003675 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003676 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003677
3678 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3679
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003680 mDispatcher->onWindowInfosChanged(
3681 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003682
3683 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003685 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003686 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3687 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003688 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003689 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003690 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003691
3692 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003694 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003695 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3696 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003697 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003698 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003699 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3700 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003701
3702 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003704 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003705 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3706 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003707 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003708 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003709 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3710 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003711
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003713 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003714 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3715 AINPUT_SOURCE_MOUSE)
3716 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3717 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003718 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003719 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003720 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003721
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003723 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003724 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3725 AINPUT_SOURCE_MOUSE)
3726 .buttonState(0)
3727 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003729 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003730 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003731
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003733 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003734 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3735 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003736 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003737 .build()));
3738 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3739
3740 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003742 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003743 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3744 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003745 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003746 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003747 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003748
3749 // No more events
3750 windowLeft->assertNoEvents();
3751 windowRight->assertNoEvents();
3752}
3753
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003754/**
3755 * Put two fingers down (and don't release them) and click the mouse button.
3756 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3757 * currently active gesture should be canceled, and the new one should proceed.
3758 */
3759TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3761 sp<FakeWindowHandle> window =
3762 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3763 window->setFrame(Rect(0, 0, 600, 800));
3764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003765 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003766
3767 const int32_t touchDeviceId = 4;
3768 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003769
3770 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003771 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3772 .deviceId(touchDeviceId)
3773 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3774 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003775
Prabir Pradhan678438e2023-04-13 19:32:51 +00003776 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3777 .deviceId(touchDeviceId)
3778 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3779 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3780 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003781 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3782 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3783
3784 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3786 .deviceId(mouseDeviceId)
3787 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3788 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3789 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3791 WithPointerCount(2u)));
3792 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3793
Prabir Pradhan678438e2023-04-13 19:32:51 +00003794 mDispatcher->notifyMotion(
3795 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3796 .deviceId(mouseDeviceId)
3797 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3798 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3799 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3800 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003801 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3802
3803 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3804 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003805 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3806 .deviceId(touchDeviceId)
3807 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3808 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3809 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003810 window->assertNoEvents();
3811}
3812
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003813TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3815
3816 sp<FakeWindowHandle> spyWindow =
3817 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3818 spyWindow->setFrame(Rect(0, 0, 600, 800));
3819 spyWindow->setTrustedOverlay(true);
3820 spyWindow->setSpy(true);
3821 sp<FakeWindowHandle> window =
3822 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3823 window->setFrame(Rect(0, 0, 600, 800));
3824
3825 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003826 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003827
3828 // Send mouse cursor to the window
3829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003830 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003831 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3832 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003833 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003834 .build()));
3835
3836 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3837 WithSource(AINPUT_SOURCE_MOUSE)));
3838 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3839 WithSource(AINPUT_SOURCE_MOUSE)));
3840
3841 window->assertNoEvents();
3842 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003843}
3844
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003845TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3846 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3847
3848 sp<FakeWindowHandle> spyWindow =
3849 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3850 spyWindow->setFrame(Rect(0, 0, 600, 800));
3851 spyWindow->setTrustedOverlay(true);
3852 spyWindow->setSpy(true);
3853 sp<FakeWindowHandle> window =
3854 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3855 window->setFrame(Rect(0, 0, 600, 800));
3856
3857 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003858 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003859
3860 // Send mouse cursor to the window
3861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003862 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003863 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3864 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003865 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003866 .build()));
3867
3868 // Move mouse cursor
3869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003870 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003871 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3872 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003873 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003874 .build()));
3875
3876 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3877 WithSource(AINPUT_SOURCE_MOUSE)));
3878 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3879 WithSource(AINPUT_SOURCE_MOUSE)));
3880 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3881 WithSource(AINPUT_SOURCE_MOUSE)));
3882 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3883 WithSource(AINPUT_SOURCE_MOUSE)));
3884 // Touch down on the window
3885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003886 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003887 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3888 AINPUT_SOURCE_TOUCHSCREEN)
3889 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003890 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003891 .build()));
3892 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3893 WithSource(AINPUT_SOURCE_MOUSE)));
3894 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3895 WithSource(AINPUT_SOURCE_MOUSE)));
3896 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3897 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3898 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3899 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3900
3901 // pilfer the motion, retaining the gesture on the spy window.
3902 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3903 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3904 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3905
3906 // Touch UP on the window
3907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003908 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003909 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3910 AINPUT_SOURCE_TOUCHSCREEN)
3911 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003912 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003913 .build()));
3914 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3915 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3916
3917 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3918 // to send a new gesture. It should again go to both windows (spy and the window below), just
3919 // like the first gesture did, before pilfering. The window configuration has not changed.
3920
3921 // One more tap - DOWN
3922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003923 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003924 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3925 AINPUT_SOURCE_TOUCHSCREEN)
3926 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003927 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003928 .build()));
3929 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3930 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3931 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3932 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3933
3934 // Touch UP on the window
3935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003936 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003937 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3938 AINPUT_SOURCE_TOUCHSCREEN)
3939 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003940 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003941 .build()));
3942 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3943 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3944 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3945 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3946
3947 window->assertNoEvents();
3948 spyWindow->assertNoEvents();
3949}
3950
Garfield Tandf26e862020-07-01 20:18:19 -07003951// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3952// directly in this test.
3953TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003955 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003956 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003957 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003958
3959 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3960
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003961 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003962
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003965 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3966 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003968 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003969 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003970 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003972 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003973 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3974 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003975 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003976 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003977 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3978 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003979
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003981 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003982 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3983 AINPUT_SOURCE_MOUSE)
3984 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3985 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003986 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003987 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003988 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003989
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003991 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003992 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3993 AINPUT_SOURCE_MOUSE)
3994 .buttonState(0)
3995 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003996 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003997 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003998 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003999
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004001 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004002 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4003 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004004 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004005 .build()));
4006 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4007
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004008 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4009 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4010 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004011 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004012 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4013 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004014 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004015 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004016 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004017}
4018
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004019/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004020 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4021 * is generated.
4022 */
4023TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4025 sp<FakeWindowHandle> window =
4026 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4027 window->setFrame(Rect(0, 0, 1200, 800));
4028
4029 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4030
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004031 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004032
4033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004034 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004035 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4036 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004037 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004038 .build()));
4039 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4040
4041 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004042 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004043 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4044}
4045
4046/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004047 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4048 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004049TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4050 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4051 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4053 sp<FakeWindowHandle> window =
4054 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4055 window->setFrame(Rect(0, 0, 1200, 800));
4056
4057 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4058
4059 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4060
4061 MotionEventBuilder hoverEnterBuilder =
4062 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4063 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4064 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4066 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4068 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4069 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4070 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4071}
4072
4073/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004074 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4075 */
4076TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4078 sp<FakeWindowHandle> window =
4079 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4080 window->setFrame(Rect(0, 0, 100, 100));
4081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004082 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004083
4084 const int32_t mouseDeviceId = 7;
4085 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004086
4087 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4089 .deviceId(mouseDeviceId)
4090 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4091 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004092 window->consumeMotionEvent(
4093 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4094
4095 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4097 .deviceId(touchDeviceId)
4098 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4099 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004100
4101 window->consumeMotionEvent(
4102 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4103 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4104}
4105
4106/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004107 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004108 * The tap causes a HOVER_EXIT event to be generated because the current event
4109 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004110 */
4111TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4113 sp<FakeWindowHandle> window =
4114 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4115 window->setFrame(Rect(0, 0, 100, 100));
4116
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004117 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004118 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4119 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4120 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004121 ASSERT_NO_FATAL_FAILURE(
4122 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4123 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004124
4125 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004126 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4127 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4128 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004129 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004130 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4131 WithSource(AINPUT_SOURCE_MOUSE))));
4132
4133 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004134 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4135 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4136
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004137 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4138 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4139 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004140 ASSERT_NO_FATAL_FAILURE(
4141 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4142 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4143}
4144
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004145TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4147 sp<FakeWindowHandle> windowDefaultDisplay =
4148 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4149 ADISPLAY_ID_DEFAULT);
4150 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4151 sp<FakeWindowHandle> windowSecondDisplay =
4152 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4153 SECOND_DISPLAY_ID);
4154 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4155
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004156 mDispatcher->onWindowInfosChanged(
4157 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004158
4159 // Set cursor position in window in default display and check that hover enter and move
4160 // events are generated.
4161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004162 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004163 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4164 AINPUT_SOURCE_MOUSE)
4165 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004166 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004167 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004168 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004169
4170 // Remove all windows in secondary display and check that no event happens on window in
4171 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004172 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4173
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004174 windowDefaultDisplay->assertNoEvents();
4175
4176 // Move cursor position in window in default display and check that only hover move
4177 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004178 mDispatcher->onWindowInfosChanged(
4179 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004181 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004182 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4183 AINPUT_SOURCE_MOUSE)
4184 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004185 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004186 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004187 windowDefaultDisplay->consumeMotionEvent(
4188 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4189 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004190 windowDefaultDisplay->assertNoEvents();
4191}
4192
Garfield Tan00f511d2019-06-12 16:55:40 -07004193TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004195
4196 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004197 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004198 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004199 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004200 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004201 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004202
4203 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4204
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004205 mDispatcher->onWindowInfosChanged(
4206 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004207
4208 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4209 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004211 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004212 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004213 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004214 windowRight->assertNoEvents();
4215}
4216
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004217TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004218 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004219 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4220 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004221 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004222
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004223 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004224 setFocusedWindow(window);
4225
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004226 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004227
Prabir Pradhan678438e2023-04-13 19:32:51 +00004228 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004229
4230 // Window should receive key down event.
4231 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4232
4233 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4234 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004235 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004236 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004237 AKEY_EVENT_FLAG_CANCELED);
4238}
4239
4240TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004242 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4243 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004244
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004246
Prabir Pradhan678438e2023-04-13 19:32:51 +00004247 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4248 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004249
4250 // Window should receive motion down event.
4251 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4252
4253 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4254 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004255 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004256 window->consumeMotionEvent(
4257 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004258}
4259
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004260TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4262 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4263 "Fake Window", ADISPLAY_ID_DEFAULT);
4264
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004265 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004266
4267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4268 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4269 .build());
4270
4271 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4272
4273 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4274 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4275 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4276
4277 // After the device has been reset, a new hovering stream can be sent to the window
4278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4279 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4280 .build());
4281 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4282}
4283
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004284TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004286 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4287 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004288 window->setFocusable(true);
4289
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004290 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004291 setFocusedWindow(window);
4292
4293 window->consumeFocusEvent(true);
4294
Prabir Pradhan678438e2023-04-13 19:32:51 +00004295 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004296 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4297 const nsecs_t injectTime = keyArgs.eventTime;
4298 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004299 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004300 // The dispatching time should be always greater than or equal to intercept key timeout.
4301 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4302 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4303 std::chrono::nanoseconds(interceptKeyTimeout).count());
4304}
4305
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004306/**
4307 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4308 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004309TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004311 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4312 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004313 window->setFocusable(true);
4314
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004315 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004316 setFocusedWindow(window);
4317
4318 window->consumeFocusEvent(true);
4319
Prabir Pradhan678438e2023-04-13 19:32:51 +00004320 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004321 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004322
4323 // Set a value that's significantly larger than the default consumption timeout. If the
4324 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4325 mFakePolicy->setInterceptKeyTimeout(600ms);
4326 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4327 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004328 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4329}
4330
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004331/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004332 * Two windows. First is a regular window. Second does not overlap with the first, and has
4333 * WATCH_OUTSIDE_TOUCH.
4334 * Both windows are owned by the same UID.
4335 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4336 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4337 */
4338TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4339 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004340 sp<FakeWindowHandle> window =
4341 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004342 window->setFrame(Rect{0, 0, 100, 100});
4343
4344 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004345 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004346 ADISPLAY_ID_DEFAULT);
4347 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4348 outsideWindow->setWatchOutsideTouch(true);
4349 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004350 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004351
4352 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004353 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4354 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4355 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004356 window->consumeMotionDown();
4357 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4358 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4359 outsideWindow->consumeMotionEvent(
4360 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004361
4362 // Ensure outsideWindow doesn't get any more events for the gesture.
4363 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4364 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4365 window->consumeMotionMove();
4366 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004367}
4368
4369/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004370 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4371 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4372 * ACTION_OUTSIDE event is sent per gesture.
4373 */
4374TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4375 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004377 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4378 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004379 window->setWatchOutsideTouch(true);
4380 window->setFrame(Rect{0, 0, 100, 100});
4381 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004382 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4383 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004384 secondWindow->setFrame(Rect{100, 100, 200, 200});
4385 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004386 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4387 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004388 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004389 mDispatcher->onWindowInfosChanged(
4390 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004391
4392 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004393 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4394 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4395 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004396 window->assertNoEvents();
4397 secondWindow->assertNoEvents();
4398
4399 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4400 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004401 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4402 ADISPLAY_ID_DEFAULT,
4403 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004404 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4405 window->consumeMotionEvent(
4406 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004407 secondWindow->consumeMotionDown();
4408 thirdWindow->assertNoEvents();
4409
4410 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4411 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004412 mDispatcher->notifyMotion(
4413 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4414 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004415 window->assertNoEvents();
4416 secondWindow->consumeMotionMove();
4417 thirdWindow->consumeMotionDown();
4418}
4419
Prabir Pradhan814fe082022-07-22 20:22:18 +00004420TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004422 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4423 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004424 window->setFocusable(true);
4425
Patrick Williamsd828f302023-04-28 17:52:08 -05004426 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004427 setFocusedWindow(window);
4428
4429 window->consumeFocusEvent(true);
4430
Prabir Pradhan678438e2023-04-13 19:32:51 +00004431 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4432 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4433 mDispatcher->notifyKey(keyDown);
4434 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004435
4436 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4437 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4438
4439 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004440 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004441
4442 window->consumeFocusEvent(false);
4443
Prabir Pradhan678438e2023-04-13 19:32:51 +00004444 mDispatcher->notifyKey(keyDown);
4445 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004446 window->assertNoEvents();
4447}
4448
Arthur Hung96483742022-11-15 03:30:48 +00004449TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4451 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4452 "Fake Window", ADISPLAY_ID_DEFAULT);
4453 // Ensure window is non-split and have some transform.
4454 window->setPreventSplitting(true);
4455 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004456 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004457
4458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004459 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004460 {50, 50}))
4461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4462 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4463
4464 const MotionEvent secondFingerDownEvent =
4465 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4466 .displayId(ADISPLAY_ID_DEFAULT)
4467 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004468 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4469 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004470 .build();
4471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004472 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004473 InputEventInjectionSync::WAIT_FOR_RESULT))
4474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4475
4476 const MotionEvent* event = window->consumeMotion();
4477 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4478 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4479 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4480 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4481 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4482}
4483
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004484/**
4485 * Two windows: a splittable and a non-splittable.
4486 * The non-splittable window shouldn't receive any "incomplete" gestures.
4487 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4488 * The second pointer should be dropped because the initial window is splittable, so it won't get
4489 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4490 * "incomplete" gestures.
4491 */
4492TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4494 sp<FakeWindowHandle> leftWindow =
4495 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4496 ADISPLAY_ID_DEFAULT);
4497 leftWindow->setPreventSplitting(false);
4498 leftWindow->setFrame(Rect(0, 0, 100, 100));
4499 sp<FakeWindowHandle> rightWindow =
4500 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4501 ADISPLAY_ID_DEFAULT);
4502 rightWindow->setPreventSplitting(true);
4503 rightWindow->setFrame(Rect(100, 100, 200, 200));
4504 mDispatcher->onWindowInfosChanged(
4505 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4506
4507 // Touch down on left, splittable window
4508 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4509 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4510 .build());
4511 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4512
4513 mDispatcher->notifyMotion(
4514 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4515 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4516 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4517 .build());
4518 leftWindow->assertNoEvents();
4519 rightWindow->assertNoEvents();
4520}
4521
Harry Cuttsb166c002023-05-09 13:06:05 +00004522TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4524 sp<FakeWindowHandle> window =
4525 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4526 window->setFrame(Rect(0, 0, 400, 400));
4527 sp<FakeWindowHandle> trustedOverlay =
4528 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4529 ADISPLAY_ID_DEFAULT);
4530 trustedOverlay->setSpy(true);
4531 trustedOverlay->setTrustedOverlay(true);
4532
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004533 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004534
4535 // Start a three-finger touchpad swipe
4536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4537 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4538 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4539 .build());
4540 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4541 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4542 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4543 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4544 .build());
4545 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4546 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4547 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4548 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4549 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4550 .build());
4551
4552 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4553 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4554 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4555
4556 // Move the swipe a bit
4557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4558 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4559 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4560 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4561 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4562 .build());
4563
4564 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4565
4566 // End the swipe
4567 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4568 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4569 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4570 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4571 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4572 .build());
4573 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4574 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4575 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4576 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4577 .build());
4578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4579 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4580 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4581 .build());
4582
4583 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4584 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4585 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4586
4587 window->assertNoEvents();
4588}
4589
4590TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4591 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4592 sp<FakeWindowHandle> window =
4593 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4594 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004595 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004596
4597 // Start a three-finger touchpad swipe
4598 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4599 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4600 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4601 .build());
4602 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4603 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4604 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4605 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4606 .build());
4607 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4608 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4609 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4610 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4611 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4612 .build());
4613
4614 // Move the swipe a bit
4615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4616 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4617 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4618 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4619 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4620 .build());
4621
4622 // End the swipe
4623 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4624 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4625 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4626 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4627 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4628 .build());
4629 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4630 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4631 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4632 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4633 .build());
4634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4635 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4636 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4637 .build());
4638
4639 window->assertNoEvents();
4640}
4641
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004642/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004643 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4644 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004645 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004646 */
4647TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4649 sp<FakeWindowHandle> window =
4650 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4651 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004652 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004653
4654 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4655 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4656 .downTime(baseTime + 10)
4657 .eventTime(baseTime + 10)
4658 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4659 .build());
4660
4661 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4662
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004663 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004664 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004665
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004666 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004667
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004668 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4669 .downTime(baseTime + 10)
4670 .eventTime(baseTime + 30)
4671 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4672 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4673 .build());
4674
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004675 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4676
4677 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004678 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4679 .downTime(baseTime + 10)
4680 .eventTime(baseTime + 40)
4681 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4682 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4683 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004684
4685 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4686
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4688 .downTime(baseTime + 10)
4689 .eventTime(baseTime + 50)
4690 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4691 .build());
4692
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004693 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4694
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4696 .downTime(baseTime + 60)
4697 .eventTime(baseTime + 60)
4698 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4699 .build());
4700
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004701 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004702}
4703
4704/**
Hu Guo771a7692023-09-17 20:51:08 +08004705 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4706 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4707 * its coordinates should be converted by the transform of the windows of target screen.
4708 */
4709TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4710 // This case will create a window and a spy window on the default display and mirror
4711 // window on the second display. cancel event is sent through spy window pilferPointers
4712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4713
4714 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4715 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4716 spyWindowDefaultDisplay->setTrustedOverlay(true);
4717 spyWindowDefaultDisplay->setSpy(true);
4718
4719 sp<FakeWindowHandle> windowDefaultDisplay =
4720 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4721 ADISPLAY_ID_DEFAULT);
4722 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4723
4724 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4725 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4726
4727 // Add the windows to the dispatcher
4728 mDispatcher->onWindowInfosChanged(
4729 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4730 *windowSecondDisplay->getInfo()},
4731 {},
4732 0,
4733 0});
4734
4735 // Send down to ADISPLAY_ID_DEFAULT
4736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4738 {100, 100}))
4739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4740
4741 spyWindowDefaultDisplay->consumeMotionDown();
4742 windowDefaultDisplay->consumeMotionDown();
4743
4744 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4745
4746 // windowDefaultDisplay gets cancel
4747 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4748 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4749
4750 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4751 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4752 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4753 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4754 EXPECT_EQ(100, event->getX(0));
4755 EXPECT_EQ(100, event->getY(0));
4756}
4757
4758/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004759 * Ensure the correct coordinate spaces are used by InputDispatcher.
4760 *
4761 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4762 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4763 * space.
4764 */
4765class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4766public:
4767 void SetUp() override {
4768 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004769 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004770 }
4771
4772 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4773 gui::DisplayInfo info;
4774 info.displayId = displayId;
4775 info.transform = transform;
4776 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004777 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004778 }
4779
4780 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4781 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004782 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004783 }
4784
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004785 void removeAllWindowsAndDisplays() {
4786 mDisplayInfos.clear();
4787 mWindowInfos.clear();
4788 }
4789
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004790 // Set up a test scenario where the display has a scaled projection and there are two windows
4791 // on the display.
4792 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4793 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4794 // respectively.
4795 ui::Transform displayTransform;
4796 displayTransform.set(2, 0, 0, 4);
4797 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4798
4799 std::shared_ptr<FakeApplicationHandle> application =
4800 std::make_shared<FakeApplicationHandle>();
4801
4802 // Add two windows to the display. Their frames are represented in the display space.
4803 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004804 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4805 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004806 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4807 addWindow(firstWindow);
4808
4809 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004810 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4811 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004812 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4813 addWindow(secondWindow);
4814 return {std::move(firstWindow), std::move(secondWindow)};
4815 }
4816
4817private:
4818 std::vector<gui::DisplayInfo> mDisplayInfos;
4819 std::vector<gui::WindowInfo> mWindowInfos;
4820};
4821
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004822TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004823 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4824 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004825 // selected so that if the hit test was performed with the point and the bounds being in
4826 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004827 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4828 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4829 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004830
4831 firstWindow->consumeMotionDown();
4832 secondWindow->assertNoEvents();
4833}
4834
4835// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4836// the event should be treated as being in the logical display space.
4837TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4838 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4839 // Send down to the first window. The point is represented in the logical display space. The
4840 // point is selected so that if the hit test was done in logical display space, then it would
4841 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004842 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004843 PointF{75 * 2, 55 * 4});
4844
4845 firstWindow->consumeMotionDown();
4846 secondWindow->assertNoEvents();
4847}
4848
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004849// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4850// event should be treated as being in the logical display space.
4851TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4852 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4853
4854 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4855 ui::Transform injectedEventTransform;
4856 injectedEventTransform.set(matrix);
4857 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4858 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4859
4860 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4861 .displayId(ADISPLAY_ID_DEFAULT)
4862 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004863 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004864 .x(untransformedPoint.x)
4865 .y(untransformedPoint.y))
4866 .build();
4867 event.transform(matrix);
4868
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004869 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004870 InputEventInjectionSync::WAIT_FOR_RESULT);
4871
4872 firstWindow->consumeMotionDown();
4873 secondWindow->assertNoEvents();
4874}
4875
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004876TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4877 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4878
4879 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004880 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4881 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4882 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004883
4884 firstWindow->assertNoEvents();
4885 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004886 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004887 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4888
4889 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4890 EXPECT_EQ(300, event->getRawX(0));
4891 EXPECT_EQ(880, event->getRawY(0));
4892
4893 // Ensure that the x and y values are in the window's coordinate space.
4894 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4895 // the logical display space. This will be the origin of the window space.
4896 EXPECT_EQ(100, event->getX(0));
4897 EXPECT_EQ(80, event->getY(0));
4898}
4899
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004900TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4901 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4902 // The monitor will always receive events in the logical display's coordinate space, because
4903 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004904 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004905
4906 // Send down to the first window.
4907 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4908 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4909 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4910 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4911
4912 // Second pointer goes down on second window.
4913 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4914 ADISPLAY_ID_DEFAULT,
4915 {PointF{50, 100}, PointF{150, 220}}));
4916 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4917 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4918 {1, PointF{300, 880}}};
4919 monitor.consumeMotionEvent(
4920 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4921
4922 mDispatcher->cancelCurrentTouch();
4923
4924 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4925 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4926 monitor.consumeMotionEvent(
4927 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4928}
4929
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004930TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4931 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4932
4933 // Send down to the first window.
4934 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4935 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4936 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4937
4938 // The pointer is transferred to the second window, and the second window receives it in the
4939 // correct coordinate space.
4940 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4941 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4942 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4943}
4944
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004945TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4946 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4947
4948 // Send hover move to the second window, and ensure it shows up as hover enter.
4949 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4950 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4951 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4952 WithCoords(100, 80), WithRawCoords(300, 880)));
4953
4954 // Touch down at the same location and ensure a hover exit is synthesized.
4955 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4956 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4957 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4958 WithRawCoords(300, 880)));
4959 secondWindow->consumeMotionEvent(
4960 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4961 secondWindow->assertNoEvents();
4962 firstWindow->assertNoEvents();
4963}
4964
Prabir Pradhan453ae732023-10-13 14:30:14 +00004965// Same as above, but while the window is being mirrored.
4966TEST_F(InputDispatcherDisplayProjectionTest,
4967 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4968 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4969
4970 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4971 ui::Transform secondDisplayTransform;
4972 secondDisplayTransform.set(matrix);
4973 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4974
4975 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4976 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4977 addWindow(secondWindowClone);
4978
4979 // Send hover move to the second window, and ensure it shows up as hover enter.
4980 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4981 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4982 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4983 WithCoords(100, 80), WithRawCoords(300, 880)));
4984
4985 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4986 // display.
4987 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4988 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4989 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4990 WithRawCoords(300, 880)));
4991 secondWindow->consumeMotionEvent(
4992 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4993 secondWindow->assertNoEvents();
4994 firstWindow->assertNoEvents();
4995}
4996
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004997TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4998 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4999
5000 // Send hover enter to second window
5001 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5002 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5003 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5004 WithCoords(100, 80), WithRawCoords(300, 880)));
5005
5006 mDispatcher->cancelCurrentTouch();
5007
5008 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5009 WithRawCoords(300, 880)));
5010 secondWindow->assertNoEvents();
5011 firstWindow->assertNoEvents();
5012}
5013
Prabir Pradhan453ae732023-10-13 14:30:14 +00005014// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005015TEST_F(InputDispatcherDisplayProjectionTest,
5016 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5017 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5018
5019 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5020 ui::Transform secondDisplayTransform;
5021 secondDisplayTransform.set(matrix);
5022 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5023
5024 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5025 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5026 addWindow(secondWindowClone);
5027
5028 // Send hover enter to second window
5029 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5030 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5031 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5032 WithCoords(100, 80), WithRawCoords(300, 880),
5033 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5034
5035 mDispatcher->cancelCurrentTouch();
5036
5037 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5038 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5039 WithRawCoords(300, 880),
5040 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5041 secondWindow->assertNoEvents();
5042 firstWindow->assertNoEvents();
5043}
5044
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005045/** Ensure consistent behavior of InputDispatcher in all orientations. */
5046class InputDispatcherDisplayOrientationFixture
5047 : public InputDispatcherDisplayProjectionTest,
5048 public ::testing::WithParamInterface<ui::Rotation> {};
5049
5050// This test verifies the touchable region of a window for all rotations of the display by tapping
5051// in different locations on the display, specifically points close to the four corners of a
5052// window.
5053TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5054 constexpr static int32_t displayWidth = 400;
5055 constexpr static int32_t displayHeight = 800;
5056
5057 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5058
5059 const auto rotation = GetParam();
5060
5061 // Set up the display with the specified rotation.
5062 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5063 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5064 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5065 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5066 logicalDisplayWidth, logicalDisplayHeight);
5067 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5068
5069 // Create a window with its bounds determined in the logical display.
5070 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5071 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5072 sp<FakeWindowHandle> window =
5073 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5074 window->setFrame(frameInDisplay, displayTransform);
5075 addWindow(window);
5076
5077 // The following points in logical display space should be inside the window.
5078 static const std::array<vec2, 4> insidePoints{
5079 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5080 for (const auto pointInsideWindow : insidePoints) {
5081 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5082 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005083 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5084 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5085 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005086 window->consumeMotionDown();
5087
Prabir Pradhan678438e2023-04-13 19:32:51 +00005088 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5089 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5090 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005091 window->consumeMotionUp();
5092 }
5093
5094 // The following points in logical display space should be outside the window.
5095 static const std::array<vec2, 5> outsidePoints{
5096 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5097 for (const auto pointOutsideWindow : outsidePoints) {
5098 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5099 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005100 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5101 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5102 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005103
Prabir Pradhan678438e2023-04-13 19:32:51 +00005104 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5105 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5106 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005107 }
5108 window->assertNoEvents();
5109}
5110
5111// Run the precision tests for all rotations.
5112INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5113 InputDispatcherDisplayOrientationFixture,
5114 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5115 ui::ROTATION_270),
5116 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5117 return ftl::enum_string(testParamInfo.param);
5118 });
5119
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005120using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5121 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005122
5123class TransferTouchFixture : public InputDispatcherTest,
5124 public ::testing::WithParamInterface<TransferFunction> {};
5125
5126TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005128
5129 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005130 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005131 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5132 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005133 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005134 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005135 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5136 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005137 sp<FakeWindowHandle> wallpaper =
5138 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5139 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005140 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005141 mDispatcher->onWindowInfosChanged(
5142 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005143
5144 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5146 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005147
Svet Ganov5d3bc372020-01-26 23:11:07 -08005148 // Only the first window should get the down event
5149 firstWindow->consumeMotionDown();
5150 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005151 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005152
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005153 // Transfer touch to the second window
5154 TransferFunction f = GetParam();
5155 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5156 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005157 // The first window gets cancel and the second gets down
5158 firstWindow->consumeMotionCancel();
5159 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005160 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005161
5162 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005163 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5164 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005165 // The first window gets no events and the second gets up
5166 firstWindow->assertNoEvents();
5167 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005168 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005169}
5170
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005171/**
5172 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5173 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5174 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5175 * natural to the user.
5176 * In this test, we are sending a pointer to both spy window and first window. We then try to
5177 * transfer touch to the second window. The dispatcher should identify the first window as the
5178 * one that should lose the gesture, and therefore the action should be to move the gesture from
5179 * the first window to the second.
5180 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5181 * the other API, as well.
5182 */
5183TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5184 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5185
5186 // Create a couple of windows + a spy window
5187 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005188 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005189 spyWindow->setTrustedOverlay(true);
5190 spyWindow->setSpy(true);
5191 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005192 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005193 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005194 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005195
5196 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005197 mDispatcher->onWindowInfosChanged(
5198 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005199
5200 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005201 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5202 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005203 // Only the first window and spy should get the down event
5204 spyWindow->consumeMotionDown();
5205 firstWindow->consumeMotionDown();
5206
5207 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5208 // if f === 'transferTouch'.
5209 TransferFunction f = GetParam();
5210 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5211 ASSERT_TRUE(success);
5212 // The first window gets cancel and the second gets down
5213 firstWindow->consumeMotionCancel();
5214 secondWindow->consumeMotionDown();
5215
5216 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005217 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5218 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005219 // The first window gets no events and the second+spy get up
5220 firstWindow->assertNoEvents();
5221 spyWindow->consumeMotionUp();
5222 secondWindow->consumeMotionUp();
5223}
5224
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005225TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005227
5228 PointF touchPoint = {10, 10};
5229
5230 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005231 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005232 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5233 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005234 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005235 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005236 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5237 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005238 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005239
5240 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005241 mDispatcher->onWindowInfosChanged(
5242 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005243
5244 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005245 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5246 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5247 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005248 // Only the first window should get the down event
5249 firstWindow->consumeMotionDown();
5250 secondWindow->assertNoEvents();
5251
5252 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005253 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5254 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005255 // Only the first window should get the pointer down event
5256 firstWindow->consumeMotionPointerDown(1);
5257 secondWindow->assertNoEvents();
5258
5259 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005260 TransferFunction f = GetParam();
5261 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5262 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005263 // The first window gets cancel and the second gets down and pointer down
5264 firstWindow->consumeMotionCancel();
5265 secondWindow->consumeMotionDown();
5266 secondWindow->consumeMotionPointerDown(1);
5267
5268 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005269 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5270 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005271 // The first window gets nothing and the second gets pointer up
5272 firstWindow->assertNoEvents();
5273 secondWindow->consumeMotionPointerUp(1);
5274
5275 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005276 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5277 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005278 // The first window gets nothing and the second gets up
5279 firstWindow->assertNoEvents();
5280 secondWindow->consumeMotionUp();
5281}
5282
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5285
5286 // Create a couple of windows
5287 sp<FakeWindowHandle> firstWindow =
5288 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5289 ADISPLAY_ID_DEFAULT);
5290 firstWindow->setDupTouchToWallpaper(true);
5291 sp<FakeWindowHandle> secondWindow =
5292 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5293 ADISPLAY_ID_DEFAULT);
5294 secondWindow->setDupTouchToWallpaper(true);
5295
5296 sp<FakeWindowHandle> wallpaper1 =
5297 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5298 wallpaper1->setIsWallpaper(true);
5299
5300 sp<FakeWindowHandle> wallpaper2 =
5301 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5302 wallpaper2->setIsWallpaper(true);
5303 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005304 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5305 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5306 {},
5307 0,
5308 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005309
5310 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005311 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5312 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005313
5314 // Only the first window should get the down event
5315 firstWindow->consumeMotionDown();
5316 secondWindow->assertNoEvents();
5317 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5318 wallpaper2->assertNoEvents();
5319
5320 // Transfer touch focus to the second window
5321 TransferFunction f = GetParam();
5322 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5323 ASSERT_TRUE(success);
5324
5325 // The first window gets cancel and the second gets down
5326 firstWindow->consumeMotionCancel();
5327 secondWindow->consumeMotionDown();
5328 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5329 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5330
5331 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005332 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5333 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005334 // The first window gets no events and the second gets up
5335 firstWindow->assertNoEvents();
5336 secondWindow->consumeMotionUp();
5337 wallpaper1->assertNoEvents();
5338 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5339}
5340
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005341// For the cases of single pointer touch and two pointers non-split touch, the api's
5342// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5343// for the case where there are multiple pointers split across several windows.
5344INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5345 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005346 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5347 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005348 return dispatcher->transferTouch(destChannelToken,
5349 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005350 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005351 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5352 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005353 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005354 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005355 }));
5356
Svet Ganov5d3bc372020-01-26 23:11:07 -08005357TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005359
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005360 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005361 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5362 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005363 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005364
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005365 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005366 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5367 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005368 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005369
5370 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005371 mDispatcher->onWindowInfosChanged(
5372 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005373
5374 PointF pointInFirst = {300, 200};
5375 PointF pointInSecond = {300, 600};
5376
5377 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005378 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5379 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5380 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005381 // Only the first window should get the down event
5382 firstWindow->consumeMotionDown();
5383 secondWindow->assertNoEvents();
5384
5385 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005386 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5387 ADISPLAY_ID_DEFAULT,
5388 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005389 // The first window gets a move and the second a down
5390 firstWindow->consumeMotionMove();
5391 secondWindow->consumeMotionDown();
5392
5393 // Transfer touch focus to the second window
5394 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5395 // The first window gets cancel and the new gets pointer down (it already saw down)
5396 firstWindow->consumeMotionCancel();
5397 secondWindow->consumeMotionPointerDown(1);
5398
5399 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005400 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5401 ADISPLAY_ID_DEFAULT,
5402 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005403 // The first window gets nothing and the second gets pointer up
5404 firstWindow->assertNoEvents();
5405 secondWindow->consumeMotionPointerUp(1);
5406
5407 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5409 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005410 // The first window gets nothing and the second gets up
5411 firstWindow->assertNoEvents();
5412 secondWindow->consumeMotionUp();
5413}
5414
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005415// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5416// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5417// touch is not supported, so the touch should continue on those windows and the transferred-to
5418// window should get nothing.
5419TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5421
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005422 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005423 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5424 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005425 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005426
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005427 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005428 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5429 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005430 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005431
5432 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005433 mDispatcher->onWindowInfosChanged(
5434 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005435
5436 PointF pointInFirst = {300, 200};
5437 PointF pointInSecond = {300, 600};
5438
5439 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005440 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5441 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5442 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005443 // Only the first window should get the down event
5444 firstWindow->consumeMotionDown();
5445 secondWindow->assertNoEvents();
5446
5447 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005448 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5449 ADISPLAY_ID_DEFAULT,
5450 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005451 // The first window gets a move and the second a down
5452 firstWindow->consumeMotionMove();
5453 secondWindow->consumeMotionDown();
5454
5455 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005456 const bool transferred =
5457 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005458 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5459 ASSERT_FALSE(transferred);
5460 firstWindow->assertNoEvents();
5461 secondWindow->assertNoEvents();
5462
5463 // The rest of the dispatch should proceed as normal
5464 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005465 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5466 ADISPLAY_ID_DEFAULT,
5467 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005468 // The first window gets MOVE and the second gets pointer up
5469 firstWindow->consumeMotionMove();
5470 secondWindow->consumeMotionUp();
5471
5472 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005473 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5474 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005475 // The first window gets nothing and the second gets up
5476 firstWindow->consumeMotionUp();
5477 secondWindow->assertNoEvents();
5478}
5479
Arthur Hungabbb9d82021-09-01 14:52:30 +00005480// This case will create two windows and one mirrored window on the default display and mirror
5481// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5482// the windows info of second display before default display.
5483TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5485 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005486 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005487 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005488 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005489 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005490 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005491
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005492 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005493 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005494
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005495 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005496 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005497
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005498 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005499 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005500
5501 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005502 mDispatcher->onWindowInfosChanged(
5503 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5504 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5505 *secondWindowInPrimary->getInfo()},
5506 {},
5507 0,
5508 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005509
5510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005511 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005512 {50, 50}))
5513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5514
5515 // Window should receive motion event.
5516 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5517
5518 // Transfer touch focus
5519 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5520 secondWindowInPrimary->getToken()));
5521 // The first window gets cancel.
5522 firstWindowInPrimary->consumeMotionCancel();
5523 secondWindowInPrimary->consumeMotionDown();
5524
5525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005526 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005527 ADISPLAY_ID_DEFAULT, {150, 50}))
5528 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5529 firstWindowInPrimary->assertNoEvents();
5530 secondWindowInPrimary->consumeMotionMove();
5531
5532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005533 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005534 {150, 50}))
5535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5536 firstWindowInPrimary->assertNoEvents();
5537 secondWindowInPrimary->consumeMotionUp();
5538}
5539
5540// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5541// 'transferTouch' api.
5542TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5544 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005545 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005546 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005547 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005548 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005549 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005550
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005551 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005552 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005553
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005554 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005555 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005556
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005557 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005558 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005559
5560 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005561 mDispatcher->onWindowInfosChanged(
5562 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5563 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5564 *secondWindowInPrimary->getInfo()},
5565 {},
5566 0,
5567 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005568
5569 // Touch on second display.
5570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005571 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5572 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5574
5575 // Window should receive motion event.
5576 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5577
5578 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005579 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005580
5581 // The first window gets cancel.
5582 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5583 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5584
5585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005586 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005587 SECOND_DISPLAY_ID, {150, 50}))
5588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5589 firstWindowInPrimary->assertNoEvents();
5590 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5591
5592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005593 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5595 firstWindowInPrimary->assertNoEvents();
5596 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5597}
5598
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005599TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005600 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005601 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5602 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005603
Vishnu Nair47074b82020-08-14 11:54:47 -07005604 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005605 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005606 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005607
5608 window->consumeFocusEvent(true);
5609
Prabir Pradhan678438e2023-04-13 19:32:51 +00005610 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005611
5612 // Window should receive key down event.
5613 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005614
5615 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005616 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005617 mFakePolicy->assertUserActivityPoked();
5618}
5619
5620TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5621 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5622 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5623 "Fake Window", ADISPLAY_ID_DEFAULT);
5624
5625 window->setDisableUserActivity(true);
5626 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005627 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005628 setFocusedWindow(window);
5629
5630 window->consumeFocusEvent(true);
5631
5632 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5633
5634 // Window should receive key down event.
5635 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5636
5637 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005638 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005639 mFakePolicy->assertUserActivityNotPoked();
5640}
5641
5642TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5644 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5645 "Fake Window", ADISPLAY_ID_DEFAULT);
5646
5647 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005648 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005649 setFocusedWindow(window);
5650
5651 window->consumeFocusEvent(true);
5652
5653 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5654 mDispatcher->waitForIdle();
5655
5656 // System key is not passed down
5657 window->assertNoEvents();
5658
5659 // Should have poked user activity
5660 mFakePolicy->assertUserActivityPoked();
5661}
5662
5663TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5666 "Fake Window", ADISPLAY_ID_DEFAULT);
5667
5668 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005669 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005670 setFocusedWindow(window);
5671
5672 window->consumeFocusEvent(true);
5673
5674 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5675 mDispatcher->waitForIdle();
5676
5677 // System key is not passed down
5678 window->assertNoEvents();
5679
5680 // Should have poked user activity
5681 mFakePolicy->assertUserActivityPoked();
5682}
5683
5684TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5687 "Fake Window", ADISPLAY_ID_DEFAULT);
5688
5689 window->setDisableUserActivity(true);
5690 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005691 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005692 setFocusedWindow(window);
5693
5694 window->consumeFocusEvent(true);
5695
5696 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5697 mDispatcher->waitForIdle();
5698
5699 // System key is not passed down
5700 window->assertNoEvents();
5701
5702 // Should have poked user activity
5703 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005704}
5705
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005706TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5708 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5709 "Fake Window", ADISPLAY_ID_DEFAULT);
5710
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005712
5713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005714 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005715 ADISPLAY_ID_DEFAULT, {100, 100}))
5716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5717
5718 window->consumeMotionEvent(
5719 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5720
5721 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005722 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005723 mFakePolicy->assertUserActivityPoked();
5724}
5725
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005726TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005728 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5729 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005730
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005731 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005732
Prabir Pradhan678438e2023-04-13 19:32:51 +00005733 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005734 mDispatcher->waitForIdle();
5735
5736 window->assertNoEvents();
5737}
5738
5739// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5740TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005742 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5743 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005744
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005745 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005746
5747 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005748 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005749 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005750 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5751 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005752
5753 // Window should receive only the motion event
5754 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5755 window->assertNoEvents(); // Key event or focus event will not be received
5756}
5757
arthurhungea3f4fc2020-12-21 23:18:53 +08005758TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5760
arthurhungea3f4fc2020-12-21 23:18:53 +08005761 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005762 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5763 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005764 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005765
arthurhungea3f4fc2020-12-21 23:18:53 +08005766 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005767 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5768 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005769 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005770
5771 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005772 mDispatcher->onWindowInfosChanged(
5773 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005774
5775 PointF pointInFirst = {300, 200};
5776 PointF pointInSecond = {300, 600};
5777
5778 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005779 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5780 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5781 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005782 // Only the first window should get the down event
5783 firstWindow->consumeMotionDown();
5784 secondWindow->assertNoEvents();
5785
5786 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005787 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5788 ADISPLAY_ID_DEFAULT,
5789 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005790 // The first window gets a move and the second a down
5791 firstWindow->consumeMotionMove();
5792 secondWindow->consumeMotionDown();
5793
5794 // Send pointer cancel to the second window
5795 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005796 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005797 {pointInFirst, pointInSecond});
5798 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005799 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005800 // The first window gets move and the second gets cancel.
5801 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5802 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5803
5804 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005805 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5806 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005807 // The first window gets up and the second gets nothing.
5808 firstWindow->consumeMotionUp();
5809 secondWindow->assertNoEvents();
5810}
5811
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005812TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5814
5815 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005816 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005817 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005818 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5819 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5820 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5821
Harry Cutts33476232023-01-30 19:57:29 +00005822 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005823 window->assertNoEvents();
5824 mDispatcher->waitForIdle();
5825}
5826
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005827using InputDispatcherMonitorTest = InputDispatcherTest;
5828
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005829/**
5830 * Two entities that receive touch: A window, and a global monitor.
5831 * The touch goes to the window, and then the window disappears.
5832 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5833 * for the monitor, as well.
5834 * 1. foregroundWindow
5835 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5836 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005837TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5839 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005840 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005841
Prabir Pradhanfb549072023-10-05 19:17:36 +00005842 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005843
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005844 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005846 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005847 {100, 200}))
5848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5849
5850 // Both the foreground window and the global monitor should receive the touch down
5851 window->consumeMotionDown();
5852 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5853
5854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005855 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005856 ADISPLAY_ID_DEFAULT, {110, 200}))
5857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5858
5859 window->consumeMotionMove();
5860 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5861
5862 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005863 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005864 window->consumeMotionCancel();
5865 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5866
5867 // If more events come in, there will be no more foreground window to send them to. This will
5868 // cause a cancel for the monitor, as well.
5869 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005870 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005871 ADISPLAY_ID_DEFAULT, {120, 200}))
5872 << "Injection should fail because the window was removed";
5873 window->assertNoEvents();
5874 // Global monitor now gets the cancel
5875 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5876}
5877
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005878TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005880 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5881 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005882 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005883
Prabir Pradhanfb549072023-10-05 19:17:36 +00005884 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005885
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005887 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005889 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005890 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005891}
5892
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005893TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005894 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005895
Chris Yea209fde2020-07-22 13:54:51 -07005896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005897 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5898 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005899 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005900
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005902 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005904 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005905 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005906
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005907 // Pilfer pointers from the monitor.
5908 // This should not do anything and the window should continue to receive events.
5909 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005910
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005912 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005913 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005915
5916 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5917 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005918}
5919
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005920TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005921 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005922 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5923 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005924 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005925 window->setWindowOffset(20, 40);
5926 window->setWindowTransform(0, 1, -1, 0);
5927
Prabir Pradhanfb549072023-10-05 19:17:36 +00005928 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005929
5930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005931 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005932 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5933 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5934 MotionEvent* event = monitor.consumeMotion();
5935 // Even though window has transform, gesture monitor must not.
5936 ASSERT_EQ(ui::Transform(), event->getTransform());
5937}
5938
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005939TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005941 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005942
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005943 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005944 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005945 << "Injection should fail if there is a monitor, but no touchable window";
5946 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005947}
5948
chaviw81e2bb92019-12-18 15:03:51 -08005949TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005951 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5952 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005953
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005954 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005955
5956 NotifyMotionArgs motionArgs =
5957 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5958 ADISPLAY_ID_DEFAULT);
5959
Prabir Pradhan678438e2023-04-13 19:32:51 +00005960 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005961 // Window should receive motion down event.
5962 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5963
5964 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005965 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005966 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5967 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5968 motionArgs.pointerCoords[0].getX() - 10);
5969
Prabir Pradhan678438e2023-04-13 19:32:51 +00005970 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005971 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005972 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005973}
5974
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005975/**
5976 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5977 * the device default right away. In the test scenario, we check both the default value,
5978 * and the action of enabling / disabling.
5979 */
5980TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005982 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5983 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005984 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005985
5986 // Set focused application.
5987 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005988 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005989
5990 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005992 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005993 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005994
5995 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005996 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005997 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005998 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005999
6000 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006001 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006002 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006003 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006004 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006005 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006006 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006007 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006008
6009 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006010 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006011 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006012 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006013
6014 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006015 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006016 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006017 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006018 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006019 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006020 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006021 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006022
6023 window->assertNoEvents();
6024}
6025
Gang Wange9087892020-01-07 12:17:14 -05006026TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006028 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6029 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006030
6031 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006032 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006033
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006034 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006035 setFocusedWindow(window);
6036
Harry Cutts33476232023-01-30 19:57:29 +00006037 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006038
Prabir Pradhan678438e2023-04-13 19:32:51 +00006039 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6040 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006041
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006042 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006043 ASSERT_NE(event, nullptr);
6044
6045 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6046 ASSERT_NE(verified, nullptr);
6047 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6048
6049 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6050 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6051 ASSERT_EQ(keyArgs.source, verified->source);
6052 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6053
6054 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6055
6056 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006057 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006058 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006059 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6060 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6061 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6062 ASSERT_EQ(0, verifiedKey.repeatCount);
6063}
6064
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006065TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006067 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6068 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006069
6070 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6071
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006072 ui::Transform transform;
6073 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6074
6075 gui::DisplayInfo displayInfo;
6076 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6077 displayInfo.transform = transform;
6078
Patrick Williamsd828f302023-04-28 17:52:08 -05006079 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006080
Prabir Pradhan678438e2023-04-13 19:32:51 +00006081 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006082 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6083 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006084 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006085
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006086 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006087 ASSERT_NE(event, nullptr);
6088
6089 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6090 ASSERT_NE(verified, nullptr);
6091 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6092
6093 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6094 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6095 EXPECT_EQ(motionArgs.source, verified->source);
6096 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6097
6098 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6099
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006100 const vec2 rawXY =
6101 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6102 motionArgs.pointerCoords[0].getXYValue());
6103 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6104 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006105 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006106 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006107 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006108 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6109 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6110}
6111
chaviw09c8d2d2020-08-24 15:48:26 -07006112/**
6113 * Ensure that separate calls to sign the same data are generating the same key.
6114 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6115 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6116 * tests.
6117 */
6118TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6119 KeyEvent event = getTestKeyEvent();
6120 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6121
6122 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6123 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6124 ASSERT_EQ(hmac1, hmac2);
6125}
6126
6127/**
6128 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6129 */
6130TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6131 KeyEvent event = getTestKeyEvent();
6132 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6133 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6134
6135 verifiedEvent.deviceId += 1;
6136 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6137
6138 verifiedEvent.source += 1;
6139 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6140
6141 verifiedEvent.eventTimeNanos += 1;
6142 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6143
6144 verifiedEvent.displayId += 1;
6145 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6146
6147 verifiedEvent.action += 1;
6148 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6149
6150 verifiedEvent.downTimeNanos += 1;
6151 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6152
6153 verifiedEvent.flags += 1;
6154 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6155
6156 verifiedEvent.keyCode += 1;
6157 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6158
6159 verifiedEvent.scanCode += 1;
6160 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6161
6162 verifiedEvent.metaState += 1;
6163 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6164
6165 verifiedEvent.repeatCount += 1;
6166 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6167}
6168
Vishnu Nair958da932020-08-21 17:12:37 -07006169TEST_F(InputDispatcherTest, SetFocusedWindow) {
6170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6171 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006172 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006173 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006174 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006175 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6176
6177 // Top window is also focusable but is not granted focus.
6178 windowTop->setFocusable(true);
6179 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006180 mDispatcher->onWindowInfosChanged(
6181 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006182 setFocusedWindow(windowSecond);
6183
6184 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006186 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006187
6188 // Focused window should receive event.
6189 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6190 windowTop->assertNoEvents();
6191}
6192
6193TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6195 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006196 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006197 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6198
6199 window->setFocusable(true);
6200 // Release channel for window is no longer valid.
6201 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006202 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006203 setFocusedWindow(window);
6204
6205 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006206 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006207
6208 // window channel is invalid, so it should not receive any input event.
6209 window->assertNoEvents();
6210}
6211
6212TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6214 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006215 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006216 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006217 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6218
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006219 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006220 setFocusedWindow(window);
6221
6222 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006223 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006224
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006225 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006226 window->assertNoEvents();
6227}
6228
6229TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6231 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006232 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006233 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006234 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006235 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6236
6237 windowTop->setFocusable(true);
6238 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006239 mDispatcher->onWindowInfosChanged(
6240 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006241 setFocusedWindow(windowTop);
6242 windowTop->consumeFocusEvent(true);
6243
Chavi Weingarten847e8512023-03-29 00:26:09 +00006244 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006245 mDispatcher->onWindowInfosChanged(
6246 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006247 windowSecond->consumeFocusEvent(true);
6248 windowTop->consumeFocusEvent(false);
6249
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006251 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006252
6253 // Focused window should receive event.
6254 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6255}
6256
Chavi Weingarten847e8512023-03-29 00:26:09 +00006257TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6259 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006260 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006261 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006262 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006263 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6264
6265 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006266 windowSecond->setFocusable(false);
6267 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006268 mDispatcher->onWindowInfosChanged(
6269 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006270 setFocusedWindow(windowTop);
6271 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006272
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006274 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006275
6276 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006277 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006278 windowSecond->assertNoEvents();
6279}
6280
6281TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6283 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006284 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006285 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006286 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6287 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006288 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6289
6290 window->setFocusable(true);
6291 previousFocusedWindow->setFocusable(true);
6292 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006293 mDispatcher->onWindowInfosChanged(
6294 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006295 setFocusedWindow(previousFocusedWindow);
6296 previousFocusedWindow->consumeFocusEvent(true);
6297
6298 // Requesting focus on invisible window takes focus from currently focused window.
6299 setFocusedWindow(window);
6300 previousFocusedWindow->consumeFocusEvent(false);
6301
6302 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006304 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6305 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006306
6307 // Window does not get focus event or key down.
6308 window->assertNoEvents();
6309
6310 // Window becomes visible.
6311 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006313
6314 // Window receives focus event.
6315 window->consumeFocusEvent(true);
6316 // Focused window receives key down.
6317 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6318}
6319
Vishnu Nair599f1412021-06-21 10:39:58 -07006320TEST_F(InputDispatcherTest, DisplayRemoved) {
6321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6322 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006323 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006324 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6325
6326 // window is granted focus.
6327 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006328 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006329 setFocusedWindow(window);
6330 window->consumeFocusEvent(true);
6331
6332 // When a display is removed window loses focus.
6333 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6334 window->consumeFocusEvent(false);
6335}
6336
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006337/**
6338 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6339 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6340 * of the 'slipperyEnterWindow'.
6341 *
6342 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6343 * a way so that the touched location is no longer covered by the top window.
6344 *
6345 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6346 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6347 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6348 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6349 * with ACTION_DOWN).
6350 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6351 * window moved itself away from the touched location and had Flag::SLIPPERY.
6352 *
6353 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6354 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6355 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6356 *
6357 * In this test, we ensure that the event received by the bottom window has
6358 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6359 */
6360TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006361 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006362 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006363
6364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6365 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6366
6367 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006368 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006369 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006370 // Make sure this one overlaps the bottom window
6371 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6372 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6373 // one. Windows with the same owner are not considered to be occluding each other.
6374 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6375
6376 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006377 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006378 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6379
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006380 mDispatcher->onWindowInfosChanged(
6381 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006382
6383 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006384 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6385 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6386 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006387 slipperyExitWindow->consumeMotionDown();
6388 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006389 mDispatcher->onWindowInfosChanged(
6390 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006391
Prabir Pradhan678438e2023-04-13 19:32:51 +00006392 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6393 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6394 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006395
6396 slipperyExitWindow->consumeMotionCancel();
6397
6398 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6399 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6400}
6401
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006402/**
6403 * Two windows, one on the left and another on the right. The left window is slippery. The right
6404 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6405 * touch moves from the left window into the right window, the gesture should continue to go to the
6406 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6407 * reproduces a crash.
6408 */
6409TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6411
6412 sp<FakeWindowHandle> leftSlipperyWindow =
6413 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6414 leftSlipperyWindow->setSlippery(true);
6415 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6416
6417 sp<FakeWindowHandle> rightDropTouchesWindow =
6418 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6419 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6420 rightDropTouchesWindow->setDropInput(true);
6421
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006422 mDispatcher->onWindowInfosChanged(
6423 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006424
6425 // Start touch in the left window
6426 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6427 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6428 .build());
6429 leftSlipperyWindow->consumeMotionDown();
6430
6431 // And move it into the right window
6432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6433 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6434 .build());
6435
6436 // Since the right window isn't eligible to receive input, touch does not slip.
6437 // The left window continues to receive the gesture.
6438 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6439 rightDropTouchesWindow->assertNoEvents();
6440}
6441
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006442/**
6443 * A single window is on screen first. Touch is injected into that window. Next, a second window
6444 * appears. Since the first window is slippery, touch will move from the first window to the second.
6445 */
6446TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6448 sp<FakeWindowHandle> originalWindow =
6449 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6450 originalWindow->setFrame(Rect(0, 0, 200, 200));
6451 originalWindow->setSlippery(true);
6452
6453 sp<FakeWindowHandle> appearingWindow =
6454 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6455 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6456
6457 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6458
6459 // Touch down on the original window
6460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6461 injectMotionEvent(*mDispatcher,
6462 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6463 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6464 .build()));
6465 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6466
6467 // Now, a new window appears. This could be, for example, a notification shade that appears
6468 // after user starts to drag down on the launcher window.
6469 mDispatcher->onWindowInfosChanged(
6470 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6472 injectMotionEvent(*mDispatcher,
6473 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6474 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6475 .build()));
6476 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6477 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6479 injectMotionEvent(*mDispatcher,
6480 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6481 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6482 .build()));
6483 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6484
6485 originalWindow->assertNoEvents();
6486 appearingWindow->assertNoEvents();
6487}
6488
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006489TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006490 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6492
6493 sp<FakeWindowHandle> leftWindow =
6494 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6495 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006496 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006497
6498 sp<FakeWindowHandle> rightSpy =
6499 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6500 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006501 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006502 rightSpy->setSpy(true);
6503 rightSpy->setTrustedOverlay(true);
6504
6505 sp<FakeWindowHandle> rightWindow =
6506 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6507 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006508 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006510 mDispatcher->onWindowInfosChanged(
6511 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006512
6513 // Touch in the left window
6514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6515 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6516 .build());
6517 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6518 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006519 ASSERT_NO_FATAL_FAILURE(
6520 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006521
6522 // Touch another finger over the right windows
6523 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6524 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6525 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6526 .build());
6527 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6528 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6529 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6530 mDispatcher->waitForIdle();
6531 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006532 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6533 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006534
6535 // Release finger over left window. The UP actions are not treated as device interaction.
6536 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6537 // is part of the UP action, we do not treat this as device interaction.
6538 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6539 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6540 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6541 .build());
6542 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6543 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6544 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6545 mDispatcher->waitForIdle();
6546 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6547
6548 // Move remaining finger
6549 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6550 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6551 .build());
6552 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6553 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6554 mDispatcher->waitForIdle();
6555 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006556 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006557
6558 // Release all fingers
6559 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6560 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6561 .build());
6562 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6563 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6564 mDispatcher->waitForIdle();
6565 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6566}
6567
6568TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6570
6571 sp<FakeWindowHandle> window =
6572 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6573 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006574 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006575
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006576 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006577 setFocusedWindow(window);
6578 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6579
6580 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6581 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6582 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006583 ASSERT_NO_FATAL_FAILURE(
6584 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006585
6586 // The UP actions are not treated as device interaction.
6587 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6588 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6589 mDispatcher->waitForIdle();
6590 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6591}
6592
Prabir Pradhan5893d362023-11-17 04:30:40 +00006593TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6595
6596 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6597 ADISPLAY_ID_DEFAULT);
6598 left->setFrame(Rect(0, 0, 100, 100));
6599 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6600 "Right Window", ADISPLAY_ID_DEFAULT);
6601 right->setFrame(Rect(100, 0, 200, 100));
6602 sp<FakeWindowHandle> spy =
6603 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6604 spy->setFrame(Rect(0, 0, 200, 100));
6605 spy->setTrustedOverlay(true);
6606 spy->setSpy(true);
6607
6608 mDispatcher->onWindowInfosChanged(
6609 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6610
6611 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6612 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6613 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6614 mDispatcher->notifyMotion(notifyArgs);
6615
6616 const MotionEvent& leftEnter = left->consumeMotionEvent(
6617 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6618 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6619
6620 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6621 Not(WithEventId(notifyArgs.id)),
6622 Not(WithEventId(leftEnter.getId())),
6623 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6624
6625 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6626 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6627 {PointF{150, 50}});
6628 mDispatcher->notifyMotion(notifyArgs);
6629
6630 const MotionEvent& leftExit = left->consumeMotionEvent(
6631 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6632 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6633
6634 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6635 Not(WithEventId(notifyArgs.id)),
6636 Not(WithEventId(leftExit.getId())),
6637 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6638
6639 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6640}
6641
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006642class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6643protected:
6644 std::shared_ptr<FakeApplicationHandle> mApp;
6645 sp<FakeWindowHandle> mWindow;
6646
6647 virtual void SetUp() override {
6648 InputDispatcherTest::SetUp();
6649
6650 mApp = std::make_shared<FakeApplicationHandle>();
6651
6652 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6653 mWindow->setFrame(Rect(0, 0, 100, 100));
6654
6655 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6656 setFocusedWindow(mWindow);
6657 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6658 }
6659
6660 void setFallback(int32_t keycode) {
6661 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6662 return KeyEventBuilder(event).keyCode(keycode).build();
6663 });
6664 }
6665
6666 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6667 KeyEvent* event = mWindow->consumeKey(handled);
6668 ASSERT_NE(event, nullptr) << "Did not receive key event";
6669 ASSERT_THAT(*event, matcher);
6670 }
6671};
6672
6673TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6674 mDispatcher->notifyKey(
6675 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6676 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6677 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6678}
6679
6680TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6681 mDispatcher->notifyKey(
6682 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6683 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6684 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6685}
6686
6687TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6688 mDispatcher->notifyKey(
6689 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6690
6691 // Do not handle this key event.
6692 consumeKey(/*handled=*/false,
6693 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6695
6696 // Since the policy did not request any fallback to be generated, ensure there are no events.
6697 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6698}
6699
6700TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6701 setFallback(AKEYCODE_B);
6702 mDispatcher->notifyKey(
6703 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6704
6705 // Do not handle this key event.
6706 consumeKey(/*handled=*/false,
6707 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6708
6709 // Since the key was not handled, ensure the fallback event was dispatched instead.
6710 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6711 consumeKey(/*handled=*/true,
6712 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6713 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6714
6715 // Release the original key, and ensure the fallback key is also released.
6716 mDispatcher->notifyKey(
6717 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6718 consumeKey(/*handled=*/false,
6719 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6720 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6721 consumeKey(/*handled=*/true,
6722 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6723 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6724
6725 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6726 mWindow->assertNoEvents();
6727}
6728
6729TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6730 setFallback(AKEYCODE_B);
6731 mDispatcher->notifyKey(
6732 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6733
6734 // Do not handle this key event, but handle the fallback.
6735 consumeKey(/*handled=*/false,
6736 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6737 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6738 consumeKey(/*handled=*/true,
6739 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6740 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6741
6742 // Release the original key, and ensure the fallback key is also released.
6743 mDispatcher->notifyKey(
6744 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6745 // But this time, the app handles the original key.
6746 consumeKey(/*handled=*/true,
6747 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6748 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6749 // Ensure the fallback key is canceled.
6750 consumeKey(/*handled=*/true,
6751 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6752 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6753
6754 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6755 mWindow->assertNoEvents();
6756}
6757
6758TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6759 setFallback(AKEYCODE_B);
6760 mDispatcher->notifyKey(
6761 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6762
6763 // Do not handle this key event.
6764 consumeKey(/*handled=*/false,
6765 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6766 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6767 // App does not handle the fallback either, so ensure another fallback is not generated.
6768 setFallback(AKEYCODE_C);
6769 consumeKey(/*handled=*/false,
6770 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6771 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6772
6773 // Release the original key, and ensure the fallback key is also released.
6774 setFallback(AKEYCODE_B);
6775 mDispatcher->notifyKey(
6776 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6777 consumeKey(/*handled=*/false,
6778 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6779 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6780 consumeKey(/*handled=*/false,
6781 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6782 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6783
6784 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6785 mWindow->assertNoEvents();
6786}
6787
6788TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6789 setFallback(AKEYCODE_B);
6790 mDispatcher->notifyKey(
6791 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6792
6793 // Do not handle this key event, so fallback is generated.
6794 consumeKey(/*handled=*/false,
6795 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6796 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6797 consumeKey(/*handled=*/true,
6798 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6799 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6800
6801 // Release the original key, but assume the policy is misbehaving and it
6802 // generates an inconsistent fallback to the one from the DOWN event.
6803 setFallback(AKEYCODE_C);
6804 mDispatcher->notifyKey(
6805 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6806 consumeKey(/*handled=*/false,
6807 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6808 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6809 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6810 consumeKey(/*handled=*/true,
6811 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6812 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6813
6814 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6815 mWindow->assertNoEvents();
6816}
6817
6818TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6819 setFallback(AKEYCODE_B);
6820 mDispatcher->notifyKey(
6821 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6822
6823 // Do not handle this key event, so fallback is generated.
6824 consumeKey(/*handled=*/false,
6825 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6826 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6827 consumeKey(/*handled=*/true,
6828 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6829 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6830
6831 // The original key is canceled.
6832 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6833 .keyCode(AKEYCODE_A)
6834 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6835 .build());
6836 consumeKey(/*handled=*/false,
6837 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6838 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6839 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6840 // Ensure the fallback key is also canceled due to the original key being canceled.
6841 consumeKey(/*handled=*/true,
6842 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6843 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6844
6845 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6846 mWindow->assertNoEvents();
6847}
6848
Garfield Tan1c7bc862020-01-28 13:24:04 -08006849class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6850protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006851 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6852 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006853
Chris Yea209fde2020-07-22 13:54:51 -07006854 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006855 sp<FakeWindowHandle> mWindow;
6856
6857 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006858 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006859 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006860 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006861 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006862 ASSERT_EQ(OK, mDispatcher->start());
6863
6864 setUpWindow();
6865 }
6866
6867 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006868 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006869 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006870
Vishnu Nair47074b82020-08-14 11:54:47 -07006871 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006872 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006873 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006874 mWindow->consumeFocusEvent(true);
6875 }
6876
Chris Ye2ad95392020-09-01 13:44:44 -07006877 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006878 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006879 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006880 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006881 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006882
6883 // Window should receive key down event.
6884 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6885 }
6886
6887 void expectKeyRepeatOnce(int32_t repeatCount) {
6888 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006889 mWindow->consumeKeyEvent(
6890 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006891 }
6892
Chris Ye2ad95392020-09-01 13:44:44 -07006893 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006894 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006895 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006896 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006897 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006898
6899 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006900 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006901 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006902 }
6903};
6904
6905TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006906 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006907 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6908 expectKeyRepeatOnce(repeatCount);
6909 }
6910}
6911
6912TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006913 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006914 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6915 expectKeyRepeatOnce(repeatCount);
6916 }
Harry Cutts33476232023-01-30 19:57:29 +00006917 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006918 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006919 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6920 expectKeyRepeatOnce(repeatCount);
6921 }
6922}
6923
6924TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006925 sendAndConsumeKeyDown(/*deviceId=*/1);
6926 expectKeyRepeatOnce(/*repeatCount=*/1);
6927 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006928 mWindow->assertNoEvents();
6929}
6930
6931TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006932 sendAndConsumeKeyDown(/*deviceId=*/1);
6933 expectKeyRepeatOnce(/*repeatCount=*/1);
6934 sendAndConsumeKeyDown(/*deviceId=*/2);
6935 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006936 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006937 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006938 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006939 expectKeyRepeatOnce(/*repeatCount=*/2);
6940 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006941 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006942 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006943 mWindow->assertNoEvents();
6944}
6945
6946TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006947 sendAndConsumeKeyDown(/*deviceId=*/1);
6948 expectKeyRepeatOnce(/*repeatCount=*/1);
6949 sendAndConsumeKeyDown(/*deviceId=*/2);
6950 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006951 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006952 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006953 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006954 mWindow->assertNoEvents();
6955}
6956
liushenxiang42232912021-05-21 20:24:09 +08006957TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6958 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006959 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006960 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006961 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6962 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6963 mWindow->assertNoEvents();
6964}
6965
Garfield Tan1c7bc862020-01-28 13:24:04 -08006966TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006967 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006968 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006969 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006970 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006971 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6972 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6973 IdGenerator::getSource(repeatEvent->getId()));
6974 }
6975}
6976
6977TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006978 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006979 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006980
6981 std::unordered_set<int32_t> idSet;
6982 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006983 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006984 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6985 int32_t id = repeatEvent->getId();
6986 EXPECT_EQ(idSet.end(), idSet.find(id));
6987 idSet.insert(id);
6988 }
6989}
6990
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006991/* Test InputDispatcher for MultiDisplay */
6992class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6993public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006994 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006995 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006996
Chris Yea209fde2020-07-22 13:54:51 -07006997 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006998 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006999 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007000
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007001 // Set focus window for primary display, but focused display would be second one.
7002 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007003 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007004 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7005
Vishnu Nair958da932020-08-21 17:12:37 -07007006 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007007 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007008
Chris Yea209fde2020-07-22 13:54:51 -07007009 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007010 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007011 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007012 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007013 // Set focus display to second one.
7014 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7015 // Set focus window for second display.
7016 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007017 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007018 mDispatcher->onWindowInfosChanged(
7019 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007020 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007021 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007022 }
7023
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007024 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007025 InputDispatcherTest::TearDown();
7026
Chris Yea209fde2020-07-22 13:54:51 -07007027 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007028 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007029 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007030 windowInSecondary.clear();
7031 }
7032
7033protected:
Chris Yea209fde2020-07-22 13:54:51 -07007034 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007035 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007036 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007037 sp<FakeWindowHandle> windowInSecondary;
7038};
7039
7040TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7041 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007043 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007045 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007046 windowInSecondary->assertNoEvents();
7047
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007048 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007050 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007052 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007053 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007054}
7055
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007056TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007057 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007059 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007060 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007061 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007062 windowInSecondary->assertNoEvents();
7063
7064 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007066 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007067 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007068 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007069
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007070 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007071 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007072
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007073 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007074 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007075 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007076
7077 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007078 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007079 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007080 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007081 windowInSecondary->assertNoEvents();
7082}
7083
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007084// Test per-display input monitors for motion event.
7085TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007086 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007087 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007088 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007089 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007090
7091 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007093 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007095 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007096 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007097 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007098 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007099
7100 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007102 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007103 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007104 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007105 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007106 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007107 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007108
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007109 // Lift up the touch from the second display
7110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007111 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7113 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7114 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7115
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007116 // Test inject a non-pointer motion event.
7117 // If specific a display, it will dispatch to the focused window of particular display,
7118 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007120 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007121 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007122 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007123 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007124 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007125 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007126}
7127
7128// Test per-display input monitors for key event.
7129TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007130 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007131 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007132 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007133 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007134 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007135
7136 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007138 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007139 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007140 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007141 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007142 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007143}
7144
Vishnu Nair958da932020-08-21 17:12:37 -07007145TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7146 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007147 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007148 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007149 mDispatcher->onWindowInfosChanged(
7150 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7151 *windowInSecondary->getInfo()},
7152 {},
7153 0,
7154 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007155 setFocusedWindow(secondWindowInPrimary);
7156 windowInPrimary->consumeFocusEvent(false);
7157 secondWindowInPrimary->consumeFocusEvent(true);
7158
7159 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7161 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007162 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007163 windowInPrimary->assertNoEvents();
7164 windowInSecondary->assertNoEvents();
7165 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7166}
7167
Arthur Hungdfd528e2021-12-08 13:23:04 +00007168TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7169 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007170 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007171 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007172 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007173
7174 // Test touch down on primary display.
7175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007176 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7178 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7179 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7180
7181 // Test touch down on second display.
7182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7185 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7186 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7187
7188 // Trigger cancel touch.
7189 mDispatcher->cancelCurrentTouch();
7190 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7191 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7192 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7193 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7194
7195 // Test inject a move motion event, no window/monitor should receive the event.
7196 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007197 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007198 ADISPLAY_ID_DEFAULT, {110, 200}))
7199 << "Inject motion event should return InputEventInjectionResult::FAILED";
7200 windowInPrimary->assertNoEvents();
7201 monitorInPrimary.assertNoEvents();
7202
7203 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007204 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007205 SECOND_DISPLAY_ID, {110, 200}))
7206 << "Inject motion event should return InputEventInjectionResult::FAILED";
7207 windowInSecondary->assertNoEvents();
7208 monitorInSecondary.assertNoEvents();
7209}
7210
Jackal Guof9696682018-10-05 12:23:23 +08007211class InputFilterTest : public InputDispatcherTest {
7212protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007213 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7214 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007215 NotifyMotionArgs motionArgs;
7216
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007217 motionArgs =
7218 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007219 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007220 motionArgs =
7221 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007222 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007223 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007224 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007225 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007226 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007227 } else {
7228 mFakePolicy->assertFilterInputEventWasNotCalled();
7229 }
7230 }
7231
7232 void testNotifyKey(bool expectToBeFiltered) {
7233 NotifyKeyArgs keyArgs;
7234
7235 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007236 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007237 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007238 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007239 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007240
7241 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007242 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007243 } else {
7244 mFakePolicy->assertFilterInputEventWasNotCalled();
7245 }
7246 }
7247};
7248
7249// Test InputFilter for MotionEvent
7250TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7251 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007252 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7253 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007254
7255 // Enable InputFilter
7256 mDispatcher->setInputFilterEnabled(true);
7257 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007258 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7259 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007260
7261 // Disable InputFilter
7262 mDispatcher->setInputFilterEnabled(false);
7263 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007264 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7265 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007266}
7267
7268// Test InputFilter for KeyEvent
7269TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7270 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007271 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007272
7273 // Enable InputFilter
7274 mDispatcher->setInputFilterEnabled(true);
7275 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007276 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007277
7278 // Disable InputFilter
7279 mDispatcher->setInputFilterEnabled(false);
7280 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007281 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007282}
7283
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007284// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7285// logical display coordinate space.
7286TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7287 ui::Transform firstDisplayTransform;
7288 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7289 ui::Transform secondDisplayTransform;
7290 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7291
7292 std::vector<gui::DisplayInfo> displayInfos(2);
7293 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7294 displayInfos[0].transform = firstDisplayTransform;
7295 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7296 displayInfos[1].transform = secondDisplayTransform;
7297
Patrick Williamsd828f302023-04-28 17:52:08 -05007298 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007299
7300 // Enable InputFilter
7301 mDispatcher->setInputFilterEnabled(true);
7302
7303 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007304 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7305 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007306}
7307
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007308class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7309protected:
7310 virtual void SetUp() override {
7311 InputDispatcherTest::SetUp();
7312
7313 /**
7314 * We don't need to enable input filter to test the injected event policy, but we enabled it
7315 * here to make the tests more realistic, since this policy only matters when inputfilter is
7316 * on.
7317 */
7318 mDispatcher->setInputFilterEnabled(true);
7319
7320 std::shared_ptr<InputApplicationHandle> application =
7321 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007322 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7323 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007324
7325 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7326 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007327 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007328 setFocusedWindow(mWindow);
7329 mWindow->consumeFocusEvent(true);
7330 }
7331
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007332 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7333 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007334 KeyEvent event;
7335
7336 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7337 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7338 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007339 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007340 const int32_t additionalPolicyFlags =
7341 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007343 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007344 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007345 policyFlags | additionalPolicyFlags));
7346
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007347 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007348 }
7349
7350 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7351 int32_t flags) {
7352 MotionEvent event;
7353 PointerProperties pointerProperties[1];
7354 PointerCoords pointerCoords[1];
7355 pointerProperties[0].clear();
7356 pointerProperties[0].id = 0;
7357 pointerCoords[0].clear();
7358 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7359 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7360
7361 ui::Transform identityTransform;
7362 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7363 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7364 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7365 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7366 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007367 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007368 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007369 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007370
7371 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007373 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007374 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007375 policyFlags | additionalPolicyFlags));
7376
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007377 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007378 }
7379
7380private:
7381 sp<FakeWindowHandle> mWindow;
7382};
7383
7384TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007385 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7386 // filter. Without it, the event will no different from a regularly injected event, and the
7387 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007388 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7389 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007390}
7391
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007392TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007393 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007394 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007395 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7396}
7397
7398TEST_F(InputFilterInjectionPolicyTest,
7399 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7400 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007401 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007402 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007403}
7404
7405TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007406 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7407 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007408}
7409
chaviwfd6d3512019-03-25 13:23:49 -07007410class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007411 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007412 InputDispatcherTest::SetUp();
7413
Chris Yea209fde2020-07-22 13:54:51 -07007414 std::shared_ptr<FakeApplicationHandle> application =
7415 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007416 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007417 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007418 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007419
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007420 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007421 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007422 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007423
7424 // Set focused application.
7425 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007426 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007427
7428 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007429 mDispatcher->onWindowInfosChanged(
7430 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007431 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007432 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007433 }
7434
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007435 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007436 InputDispatcherTest::TearDown();
7437
7438 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007439 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007440 }
7441
7442protected:
7443 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007444 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007445 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007446};
7447
7448// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7449// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7450// the onPointerDownOutsideFocus callback.
7451TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007453 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007454 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007455 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007456 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007457
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007458 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007459 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7460}
7461
7462// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7463// DOWN on the window that doesn't have focus. Ensure no window received the
7464// onPointerDownOutsideFocus callback.
7465TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7468 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007470 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007471
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007472 ASSERT_TRUE(mDispatcher->waitForIdle());
7473 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007474}
7475
7476// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7477// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7478TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007480 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007481 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007482 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007483
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007484 ASSERT_TRUE(mDispatcher->waitForIdle());
7485 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007486}
7487
7488// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7489// DOWN on the window that already has focus. Ensure no window received the
7490// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007491TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007493 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007494 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007496 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007497
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007498 ASSERT_TRUE(mDispatcher->waitForIdle());
7499 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007500}
7501
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007502// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7503// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7504TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7505 const MotionEvent event =
7506 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7507 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007508 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007509 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7510 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7513 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7514
7515 ASSERT_TRUE(mDispatcher->waitForIdle());
7516 mFakePolicy->assertOnPointerDownWasNotCalled();
7517 // Ensure that the unfocused window did not receive any FOCUS events.
7518 mUnfocusedWindow->assertNoEvents();
7519}
7520
chaviwaf87b3e2019-10-01 16:59:28 -07007521// These tests ensures we can send touch events to a single client when there are multiple input
7522// windows that point to the same client token.
7523class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7524 virtual void SetUp() override {
7525 InputDispatcherTest::SetUp();
7526
Chris Yea209fde2020-07-22 13:54:51 -07007527 std::shared_ptr<FakeApplicationHandle> application =
7528 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007529 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7530 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007531 mWindow1->setFrame(Rect(0, 0, 100, 100));
7532
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007533 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7534 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007535 mWindow2->setFrame(Rect(100, 100, 200, 200));
7536
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007537 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007538 }
7539
7540protected:
7541 sp<FakeWindowHandle> mWindow1;
7542 sp<FakeWindowHandle> mWindow2;
7543
7544 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007545 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007546 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7547 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007548 }
7549
7550 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7551 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007552 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007553 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007554
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007555 ASSERT_NE(nullptr, motionEvent)
7556 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007557
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007558 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007559 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007560
7561 for (size_t i = 0; i < points.size(); i++) {
7562 float expectedX = points[i].x;
7563 float expectedY = points[i].y;
7564
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007565 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007566 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007567 << ", got " << motionEvent->getX(i);
7568 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007569 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007570 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007571 }
7572 }
chaviw9eaa22c2020-07-01 16:21:27 -07007573
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007574 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007575 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007576 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7577 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007578
7579 // Always consume from window1 since it's the window that has the InputReceiver
7580 consumeMotionEvent(mWindow1, action, expectedPoints);
7581 }
chaviwaf87b3e2019-10-01 16:59:28 -07007582};
7583
7584TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7585 // Touch Window 1
7586 PointF touchedPoint = {10, 10};
7587 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007588 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007589
7590 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007591 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007592
7593 // Touch Window 2
7594 touchedPoint = {150, 150};
7595 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007596 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007597}
7598
chaviw9eaa22c2020-07-01 16:21:27 -07007599TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7600 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007601 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007602 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007603
7604 // Touch Window 1
7605 PointF touchedPoint = {10, 10};
7606 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007607 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007608 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007609 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007610
7611 // Touch Window 2
7612 touchedPoint = {150, 150};
7613 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007614 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7615 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007616
chaviw9eaa22c2020-07-01 16:21:27 -07007617 // Update the transform so rotation is set
7618 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007619 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007620 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7621 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007622}
7623
chaviw9eaa22c2020-07-01 16:21:27 -07007624TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007625 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007626 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007627
7628 // Touch Window 1
7629 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7630 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007631 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007632
7633 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007634 touchedPoints.push_back(PointF{150, 150});
7635 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007636 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007637
chaviw9eaa22c2020-07-01 16:21:27 -07007638 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007639 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007640 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007641
chaviw9eaa22c2020-07-01 16:21:27 -07007642 // Update the transform so rotation is set for Window 2
7643 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007644 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007645 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007646 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007647}
7648
chaviw9eaa22c2020-07-01 16:21:27 -07007649TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007650 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007651 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007652
7653 // Touch Window 1
7654 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7655 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007656 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007657
7658 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007659 touchedPoints.push_back(PointF{150, 150});
7660 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007661
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007662 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007663
7664 // Move both windows
7665 touchedPoints = {{20, 20}, {175, 175}};
7666 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7667 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7668
chaviw9eaa22c2020-07-01 16:21:27 -07007669 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007670
chaviw9eaa22c2020-07-01 16:21:27 -07007671 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007672 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007673 expectedPoints.pop_back();
7674
7675 // Touch Window 2
7676 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007677 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007678 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007679 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007680
7681 // Move both windows
7682 touchedPoints = {{20, 20}, {175, 175}};
7683 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7684 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7685
7686 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007687}
7688
7689TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7690 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007691 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007692
7693 // Touch Window 1
7694 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7695 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007696 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007697
7698 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007699 touchedPoints.push_back(PointF{150, 150});
7700 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007701
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007702 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007703
7704 // Move both windows
7705 touchedPoints = {{20, 20}, {175, 175}};
7706 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7707 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7708
chaviw9eaa22c2020-07-01 16:21:27 -07007709 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007710}
7711
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007712/**
7713 * When one of the windows is slippery, the touch should not slip into the other window with the
7714 * same input channel.
7715 */
7716TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7717 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007718 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007719
7720 // Touch down in window 1
7721 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7722 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7723 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7724
7725 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7726 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7727 // getting generated.
7728 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7729 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7730
7731 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7732}
7733
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007734/**
7735 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7736 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7737 * that the pointer is hovering over may have a different transform.
7738 */
7739TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007740 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007741
7742 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7744 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7745 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007746 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7747 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007748 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7750 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7751 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007752 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7753 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7754 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7755}
7756
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007757class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7758 virtual void SetUp() override {
7759 InputDispatcherTest::SetUp();
7760
Chris Yea209fde2020-07-22 13:54:51 -07007761 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007762 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007763 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7764 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007765 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007766 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007767 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007768
7769 // Set focused application.
7770 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7771
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007772 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007773 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007774 mWindow->consumeFocusEvent(true);
7775 }
7776
7777 virtual void TearDown() override {
7778 InputDispatcherTest::TearDown();
7779 mWindow.clear();
7780 }
7781
7782protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007783 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007784 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007785 sp<FakeWindowHandle> mWindow;
7786 static constexpr PointF WINDOW_LOCATION = {20, 20};
7787
7788 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007789 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7790 .x(WINDOW_LOCATION.x)
7791 .y(WINDOW_LOCATION.y);
7792 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7793 .pointer(touchingPointer)
7794 .build());
7795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7796 .pointer(touchingPointer)
7797 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007798 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007799
7800 sp<FakeWindowHandle> addSpyWindow() {
7801 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007802 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007803 spy->setTrustedOverlay(true);
7804 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007805 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007806 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007807 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007808 return spy;
7809 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007810};
7811
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007812// Send a tap and respond, which should not cause an ANR.
7813TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7814 tapOnWindow();
7815 mWindow->consumeMotionDown();
7816 mWindow->consumeMotionUp();
7817 ASSERT_TRUE(mDispatcher->waitForIdle());
7818 mFakePolicy->assertNotifyAnrWasNotCalled();
7819}
7820
7821// Send a regular key and respond, which should not cause an ANR.
7822TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007824 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7825 ASSERT_TRUE(mDispatcher->waitForIdle());
7826 mFakePolicy->assertNotifyAnrWasNotCalled();
7827}
7828
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007829TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7830 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007831 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007832 mWindow->consumeFocusEvent(false);
7833
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007834 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007835 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7836 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007837 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007839 // Key will not go to window because we have no focused window.
7840 // The 'no focused window' ANR timer should start instead.
7841
7842 // Now, the focused application goes away.
7843 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7844 // The key should get dropped and there should be no ANR.
7845
7846 ASSERT_TRUE(mDispatcher->waitForIdle());
7847 mFakePolicy->assertNotifyAnrWasNotCalled();
7848}
7849
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007850// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007851// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7852// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007853TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007855 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007856 WINDOW_LOCATION));
7857
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007858 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7859 ASSERT_TRUE(sequenceNum);
7860 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007861 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007862
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007863 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007864 mWindow->consumeMotionEvent(
7865 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007866 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007867 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007868}
7869
7870// Send a key to the app and have the app not respond right away.
7871TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7872 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007874 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7875 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007876 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007877 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007878 ASSERT_TRUE(mDispatcher->waitForIdle());
7879}
7880
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007881// We have a focused application, but no focused window
7882TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007883 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007884 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007885 mWindow->consumeFocusEvent(false);
7886
7887 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007889 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007890 WINDOW_LOCATION));
7891 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7892 mDispatcher->waitForIdle();
7893 mFakePolicy->assertNotifyAnrWasNotCalled();
7894
7895 // Once a focused event arrives, we get an ANR for this application
7896 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7897 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007898 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007899 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007900 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007901 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007902 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007903 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007904 ASSERT_TRUE(mDispatcher->waitForIdle());
7905}
7906
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007907/**
7908 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7909 * there will not be an ANR.
7910 */
7911TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7912 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007913 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007914 mWindow->consumeFocusEvent(false);
7915
7916 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007917 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7918 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007919 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7920 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7921
7922 // Define a valid key down event that is stale (too old).
7923 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007924 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007925 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007926
7927 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7928
7929 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007930 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007931 InputEventInjectionSync::WAIT_FOR_RESULT,
7932 INJECT_EVENT_TIMEOUT, policyFlags);
7933 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7934 << "Injection should fail because the event is stale";
7935
7936 ASSERT_TRUE(mDispatcher->waitForIdle());
7937 mFakePolicy->assertNotifyAnrWasNotCalled();
7938 mWindow->assertNoEvents();
7939}
7940
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007941// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007942// Make sure that we don't notify policy twice about the same ANR.
7943TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007944 const std::chrono::duration appTimeout = 400ms;
7945 mApplication->setDispatchingTimeout(appTimeout);
7946 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7947
Vishnu Nair47074b82020-08-14 11:54:47 -07007948 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007949 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007950 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007951
7952 // Once a focused event arrives, we get an ANR for this application
7953 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7954 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007955 const std::chrono::duration eventInjectionTimeout = 100ms;
7956 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007957 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007958 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007959 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7960 /*allowKeyRepeat=*/false);
7961 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7962 << "result=" << ftl::enum_string(result);
7963 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7964 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7965 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7966 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007967
Vishnu Naire4df8752022-09-08 09:17:55 -07007968 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007969 // ANR should not be raised again. It is up to policy to do that if it desires.
7970 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007971
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007972 // If we now get a focused window, the ANR should stop, but the policy handles that via
7973 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007974 ASSERT_TRUE(mDispatcher->waitForIdle());
7975}
7976
7977// We have a focused application, but no focused window
7978TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007979 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007980 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007981 mWindow->consumeFocusEvent(false);
7982
7983 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007984 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007985
Vishnu Naire4df8752022-09-08 09:17:55 -07007986 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7987 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007988
7989 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007990 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007991 ASSERT_TRUE(mDispatcher->waitForIdle());
7992 mWindow->assertNoEvents();
7993}
7994
7995/**
7996 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7997 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7998 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7999 * the ANR mechanism should still work.
8000 *
8001 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8002 * DOWN event, while not responding on the second one.
8003 */
8004TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8005 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008006 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008007 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8008 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8009 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008010 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008011
8012 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008013 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008014 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8015 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8016 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008017 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008018
8019 // We have now sent down and up. Let's consume first event and then ANR on the second.
8020 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8021 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008022 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008023}
8024
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008025// A spy window can receive an ANR
8026TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8027 sp<FakeWindowHandle> spy = addSpyWindow();
8028
8029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008030 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008031 WINDOW_LOCATION));
8032 mWindow->consumeMotionDown();
8033
8034 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8035 ASSERT_TRUE(sequenceNum);
8036 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008037 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008038
8039 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008040 spy->consumeMotionEvent(
8041 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008042 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008043 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008044}
8045
8046// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008047// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008048TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8049 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008050
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008052 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008053 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008055
8056 // Stuck on the ACTION_UP
8057 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008058 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008059
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008060 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008061 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008062 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8063 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008064
8065 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8066 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008067 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008068 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008069 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008070}
8071
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008072// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008073// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008074TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8075 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008076
8077 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008078 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8079 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008080
8081 mWindow->consumeMotionDown();
8082 // Stuck on the ACTION_UP
8083 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008084 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008085
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008086 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008087 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008088 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8089 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008090
8091 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8092 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008093 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008094 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008095 spy->assertNoEvents();
8096}
8097
8098TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008099 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008100
Prabir Pradhanfb549072023-10-05 19:17:36 +00008101 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008102
8103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008104 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008105 WINDOW_LOCATION));
8106
8107 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8108 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8109 ASSERT_TRUE(consumeSeq);
8110
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008111 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8112 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008113
8114 monitor.finishEvent(*consumeSeq);
8115 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8116
8117 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008118 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008119}
8120
8121// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8122// process events, you don't get an anr. When the window later becomes unresponsive again, you
8123// get an ANR again.
8124// 1. tap -> block on ACTION_UP -> receive ANR
8125// 2. consume all pending events (= queue becomes healthy again)
8126// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8127TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8128 tapOnWindow();
8129
8130 mWindow->consumeMotionDown();
8131 // Block on ACTION_UP
8132 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008133 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008134 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8135 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008136 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008137 mWindow->assertNoEvents();
8138
8139 tapOnWindow();
8140 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008141 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008142 mWindow->consumeMotionUp();
8143
8144 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008145 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008146 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008147 mWindow->assertNoEvents();
8148}
8149
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008150// If a connection remains unresponsive for a while, make sure policy is only notified once about
8151// it.
8152TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008154 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008155 WINDOW_LOCATION));
8156
8157 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008158 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008159 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008160 // 'notifyConnectionUnresponsive' should only be called once per connection
8161 mFakePolicy->assertNotifyAnrWasNotCalled();
8162 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008163 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008164 mWindow->consumeMotionEvent(
8165 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008166 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008167 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008168 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008169 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008170}
8171
8172/**
8173 * 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 -07008174 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008175 *
8176 * Warning!!!
8177 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8178 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008179 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008180 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8181 *
8182 * If that value changes, this test should also change.
8183 */
8184TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8185 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008186 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008187
8188 tapOnWindow();
8189 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8190 ASSERT_TRUE(downSequenceNum);
8191 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8192 ASSERT_TRUE(upSequenceNum);
8193 // Don't finish the events yet, and send a key
8194 // Injection will "succeed" because we will eventually give up and send the key to the focused
8195 // window even if motions are still being processed. But because the injection timeout is short,
8196 // we will receive INJECTION_TIMED_OUT as the result.
8197
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008198 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008199 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8200 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008201 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008202 // Key will not be sent to the window, yet, because the window is still processing events
8203 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008204 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8205 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8206 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8207 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008208
8209 std::this_thread::sleep_for(500ms);
8210 // if we wait long enough though, dispatcher will give up, and still send the key
8211 // to the focused window, even though we have not yet finished the motion event
8212 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8213 mWindow->finishEvent(*downSequenceNum);
8214 mWindow->finishEvent(*upSequenceNum);
8215}
8216
8217/**
8218 * If a window is processing a motion event, and then a key event comes in, the key event should
8219 * not go to the focused window until the motion is processed.
8220 * If then a new motion comes in, then the pending key event should be going to the currently
8221 * focused window right away.
8222 */
8223TEST_F(InputDispatcherSingleWindowAnr,
8224 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8225 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008226 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008227
8228 tapOnWindow();
8229 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8230 ASSERT_TRUE(downSequenceNum);
8231 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8232 ASSERT_TRUE(upSequenceNum);
8233 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008234 mDispatcher->notifyKey(
8235 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8236 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8237 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008238 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008239 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8240 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8241 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8242 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008243
8244 // Now tap down again. It should cause the pending key to go to the focused window right away.
8245 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008246 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8247 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008248 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8249 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008250 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8251 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008252 mWindow->assertNoEvents();
8253}
8254
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008255/**
8256 * Send an event to the app and have the app not respond right away.
8257 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8258 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8259 * At some point, the window becomes responsive again.
8260 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8261 */
8262TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8264 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8265 .build());
8266
8267 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8268 ASSERT_TRUE(sequenceNum);
8269 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8270 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8271
8272 mWindow->finishEvent(*sequenceNum);
8273 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8274 ASSERT_TRUE(mDispatcher->waitForIdle());
8275 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8276
8277 // Now that the window is responsive, let's continue the gesture.
8278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8279 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8280 .build());
8281
8282 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8283 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8284 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8285 .build());
8286
8287 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8288 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8289 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8290 .build());
8291 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8292 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8293 .build());
8294 // We already canceled this pointer, so the window shouldn't get any new events.
8295 mWindow->assertNoEvents();
8296
8297 // Start another one.
8298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8299 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8300 .build());
8301 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8302}
8303
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008304class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8305 virtual void SetUp() override {
8306 InputDispatcherTest::SetUp();
8307
Chris Yea209fde2020-07-22 13:54:51 -07008308 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008309 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008310 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8311 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008312 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008313 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008314 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008315
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008316 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8317 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008318 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008319 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008320
8321 // Set focused application.
8322 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008323 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008324
8325 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008326 mDispatcher->onWindowInfosChanged(
8327 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008328 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008329 mFocusedWindow->consumeFocusEvent(true);
8330 }
8331
8332 virtual void TearDown() override {
8333 InputDispatcherTest::TearDown();
8334
8335 mUnfocusedWindow.clear();
8336 mFocusedWindow.clear();
8337 }
8338
8339protected:
Chris Yea209fde2020-07-22 13:54:51 -07008340 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008341 sp<FakeWindowHandle> mUnfocusedWindow;
8342 sp<FakeWindowHandle> mFocusedWindow;
8343 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8344 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8345 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8346
8347 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8348
8349 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8350
8351private:
8352 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008354 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008355 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008357 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008358 location));
8359 }
8360};
8361
8362// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8363// should be ANR'd first.
8364TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008366 injectMotionEvent(*mDispatcher,
8367 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8368 AINPUT_SOURCE_TOUCHSCREEN)
8369 .pointer(PointerBuilder(0, ToolType::FINGER)
8370 .x(FOCUSED_WINDOW_LOCATION.x)
8371 .y(FOCUSED_WINDOW_LOCATION.y))
8372 .build()));
8373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8374 injectMotionEvent(*mDispatcher,
8375 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8376 AINPUT_SOURCE_TOUCHSCREEN)
8377 .pointer(PointerBuilder(0, ToolType::FINGER)
8378 .x(FOCUSED_WINDOW_LOCATION.x)
8379 .y(FOCUSED_WINDOW_LOCATION.y))
8380 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008381 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008382 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008383 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008384 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008385 // We consumed all events, so no ANR
8386 ASSERT_TRUE(mDispatcher->waitForIdle());
8387 mFakePolicy->assertNotifyAnrWasNotCalled();
8388
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008390 injectMotionEvent(*mDispatcher,
8391 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8392 AINPUT_SOURCE_TOUCHSCREEN)
8393 .pointer(PointerBuilder(0, ToolType::FINGER)
8394 .x(FOCUSED_WINDOW_LOCATION.x)
8395 .y(FOCUSED_WINDOW_LOCATION.y))
8396 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008397 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8398 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008399
8400 const std::chrono::duration timeout =
8401 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008402 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008403
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008404 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008405 mFocusedWindow->consumeMotionDown();
8406 // This cancel is generated because the connection was unresponsive
8407 mFocusedWindow->consumeMotionCancel();
8408 mFocusedWindow->assertNoEvents();
8409 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008410 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008411 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8412 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008413 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008414}
8415
8416// If we have 2 windows with identical timeouts that are both unresponsive,
8417// it doesn't matter which order they should have ANR.
8418// But we should receive ANR for both.
8419TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8420 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008421 mUnfocusedWindow->setDispatchingTimeout(
8422 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008423 mDispatcher->onWindowInfosChanged(
8424 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008425
8426 tapOnFocusedWindow();
8427 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008428 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008429 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8430 mFocusedWindow->getDispatchingTimeout(
8431 DISPATCHING_TIMEOUT)),
8432 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8433
8434 ASSERT_THAT(anrConnectionTokens,
8435 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8436 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008437
8438 ASSERT_TRUE(mDispatcher->waitForIdle());
8439 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008440
8441 mFocusedWindow->consumeMotionDown();
8442 mFocusedWindow->consumeMotionUp();
8443 mUnfocusedWindow->consumeMotionOutside();
8444
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008445 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8446 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008447
8448 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008449 ASSERT_THAT(responsiveTokens,
8450 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8451 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008452 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008453}
8454
8455// If a window is already not responding, the second tap on the same window should be ignored.
8456// We should also log an error to account for the dropped event (not tested here).
8457// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8458TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8459 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008460 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008461 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008462 // Receive the events, but don't respond
8463 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8464 ASSERT_TRUE(downEventSequenceNum);
8465 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8466 ASSERT_TRUE(upEventSequenceNum);
8467 const std::chrono::duration timeout =
8468 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008469 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008470
8471 // Tap once again
8472 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008473 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008474 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008475 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008476 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008477 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008478 FOCUSED_WINDOW_LOCATION));
8479 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8480 // valid touch target
8481 mUnfocusedWindow->assertNoEvents();
8482
8483 // Consume the first tap
8484 mFocusedWindow->finishEvent(*downEventSequenceNum);
8485 mFocusedWindow->finishEvent(*upEventSequenceNum);
8486 ASSERT_TRUE(mDispatcher->waitForIdle());
8487 // The second tap did not go to the focused window
8488 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008489 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008490 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8491 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008492 mFakePolicy->assertNotifyAnrWasNotCalled();
8493}
8494
8495// If you tap outside of all windows, there will not be ANR
8496TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008497 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008498 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008499 LOCATION_OUTSIDE_ALL_WINDOWS));
8500 ASSERT_TRUE(mDispatcher->waitForIdle());
8501 mFakePolicy->assertNotifyAnrWasNotCalled();
8502}
8503
8504// Since the focused window is paused, tapping on it should not produce any events
8505TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8506 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008507 mDispatcher->onWindowInfosChanged(
8508 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008509
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008510 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008511 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008512 FOCUSED_WINDOW_LOCATION));
8513
8514 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8515 ASSERT_TRUE(mDispatcher->waitForIdle());
8516 // Should not ANR because the window is paused, and touches shouldn't go to it
8517 mFakePolicy->assertNotifyAnrWasNotCalled();
8518
8519 mFocusedWindow->assertNoEvents();
8520 mUnfocusedWindow->assertNoEvents();
8521}
8522
8523/**
8524 * 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 -07008525 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008526 * If a different window becomes focused at this time, the key should go to that window instead.
8527 *
8528 * Warning!!!
8529 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8530 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008531 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008532 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8533 *
8534 * If that value changes, this test should also change.
8535 */
8536TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8537 // Set a long ANR timeout to prevent it from triggering
8538 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008539 mDispatcher->onWindowInfosChanged(
8540 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008541
8542 tapOnUnfocusedWindow();
8543 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8544 ASSERT_TRUE(downSequenceNum);
8545 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8546 ASSERT_TRUE(upSequenceNum);
8547 // Don't finish the events yet, and send a key
8548 // Injection will succeed because we will eventually give up and send the key to the focused
8549 // window even if motions are still being processed.
8550
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008551 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008552 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8553 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008555 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008556 // and the key remains pending, waiting for the touch events to be processed.
8557 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8558 // under the hood.
8559 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8560 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008561
8562 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008563 mFocusedWindow->setFocusable(false);
8564 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008565 mDispatcher->onWindowInfosChanged(
8566 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008567 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008568
8569 // Focus events should precede the key events
8570 mUnfocusedWindow->consumeFocusEvent(true);
8571 mFocusedWindow->consumeFocusEvent(false);
8572
8573 // Finish the tap events, which should unblock dispatcher
8574 mUnfocusedWindow->finishEvent(*downSequenceNum);
8575 mUnfocusedWindow->finishEvent(*upSequenceNum);
8576
8577 // Now that all queues are cleared and no backlog in the connections, the key event
8578 // can finally go to the newly focused "mUnfocusedWindow".
8579 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8580 mFocusedWindow->assertNoEvents();
8581 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008582 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008583}
8584
8585// When the touch stream is split across 2 windows, and one of them does not respond,
8586// then ANR should be raised and the touch should be canceled for the unresponsive window.
8587// The other window should not be affected by that.
8588TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8589 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008590 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8591 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8592 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008593 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008594 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008595
8596 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008597 mDispatcher->notifyMotion(
8598 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8599 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008600
8601 const std::chrono::duration timeout =
8602 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008603 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008604
8605 mUnfocusedWindow->consumeMotionDown();
8606 mFocusedWindow->consumeMotionDown();
8607 // Focused window may or may not receive ACTION_MOVE
8608 // But it should definitely receive ACTION_CANCEL due to the ANR
8609 InputEvent* event;
8610 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8611 ASSERT_TRUE(moveOrCancelSequenceNum);
8612 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8613 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008614 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008615 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8616 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8617 mFocusedWindow->consumeMotionCancel();
8618 } else {
8619 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8620 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008621 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008622 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8623 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008624
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008625 mUnfocusedWindow->assertNoEvents();
8626 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008627 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008628}
8629
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008630/**
8631 * If we have no focused window, and a key comes in, we start the ANR timer.
8632 * The focused application should add a focused window before the timer runs out to prevent ANR.
8633 *
8634 * If the user touches another application during this time, the key should be dropped.
8635 * Next, if a new focused window comes in, without toggling the focused application,
8636 * then no ANR should occur.
8637 *
8638 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8639 * but in some cases the policy may not update the focused application.
8640 */
8641TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8642 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8643 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008644 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008645 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8646 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8647 mFocusedWindow->setFocusable(false);
8648
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008649 mDispatcher->onWindowInfosChanged(
8650 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008651 mFocusedWindow->consumeFocusEvent(false);
8652
8653 // Send a key. The ANR timer should start because there is no focused window.
8654 // 'focusedApplication' will get blamed if this timer completes.
8655 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008656 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008657 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8658 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008659 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008661
8662 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8663 // then the injected touches won't cause the focused event to get dropped.
8664 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8665 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8666 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8667 // For this test, it means that the key would get delivered to the window once it becomes
8668 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008669 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008670
8671 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008672 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8673 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8674 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008675
8676 // We do not consume the motion right away, because that would require dispatcher to first
8677 // process (== drop) the key event, and by that time, ANR will be raised.
8678 // Set the focused window first.
8679 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008680 mDispatcher->onWindowInfosChanged(
8681 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008682 setFocusedWindow(mFocusedWindow);
8683 mFocusedWindow->consumeFocusEvent(true);
8684 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8685 // to another application. This could be a bug / behaviour in the policy.
8686
8687 mUnfocusedWindow->consumeMotionDown();
8688
8689 ASSERT_TRUE(mDispatcher->waitForIdle());
8690 // Should not ANR because we actually have a focused window. It was just added too slowly.
8691 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8692}
8693
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008694// These tests ensure we cannot send touch events to a window that's positioned behind a window
8695// that has feature NO_INPUT_CHANNEL.
8696// Layout:
8697// Top (closest to user)
8698// mNoInputWindow (above all windows)
8699// mBottomWindow
8700// Bottom (furthest from user)
8701class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8702 virtual void SetUp() override {
8703 InputDispatcherTest::SetUp();
8704
8705 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008706 mNoInputWindow =
8707 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8708 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008709 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008710 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008711 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8712 // It's perfectly valid for this window to not have an associated input channel
8713
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008714 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8715 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008716 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008718 mDispatcher->onWindowInfosChanged(
8719 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008720 }
8721
8722protected:
8723 std::shared_ptr<FakeApplicationHandle> mApplication;
8724 sp<FakeWindowHandle> mNoInputWindow;
8725 sp<FakeWindowHandle> mBottomWindow;
8726};
8727
8728TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8729 PointF touchedPoint = {10, 10};
8730
Prabir Pradhan678438e2023-04-13 19:32:51 +00008731 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8732 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8733 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008734
8735 mNoInputWindow->assertNoEvents();
8736 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8737 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8738 // and therefore should prevent mBottomWindow from receiving touches
8739 mBottomWindow->assertNoEvents();
8740}
8741
8742/**
8743 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8744 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8745 */
8746TEST_F(InputDispatcherMultiWindowOcclusionTests,
8747 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008748 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8749 "Window with input channel and NO_INPUT_CHANNEL",
8750 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008751
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008752 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008753 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008754 mDispatcher->onWindowInfosChanged(
8755 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008756
8757 PointF touchedPoint = {10, 10};
8758
Prabir Pradhan678438e2023-04-13 19:32:51 +00008759 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8760 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8761 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008762
8763 mNoInputWindow->assertNoEvents();
8764 mBottomWindow->assertNoEvents();
8765}
8766
Vishnu Nair958da932020-08-21 17:12:37 -07008767class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8768protected:
8769 std::shared_ptr<FakeApplicationHandle> mApp;
8770 sp<FakeWindowHandle> mWindow;
8771 sp<FakeWindowHandle> mMirror;
8772
8773 virtual void SetUp() override {
8774 InputDispatcherTest::SetUp();
8775 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008776 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8777 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8778 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008779 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8780 mWindow->setFocusable(true);
8781 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008782 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008783 }
8784};
8785
8786TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8787 // Request focus on a mirrored window
8788 setFocusedWindow(mMirror);
8789
8790 // window gets focused
8791 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008793 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008794 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8795}
8796
8797// A focused & mirrored window remains focused only if the window and its mirror are both
8798// focusable.
8799TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8800 setFocusedWindow(mMirror);
8801
8802 // window gets focused
8803 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008805 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008806 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008808 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008809 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8810
8811 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008812 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008813
8814 // window loses focus since one of the windows associated with the token in not focusable
8815 mWindow->consumeFocusEvent(false);
8816
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008817 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008818 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008819 mWindow->assertNoEvents();
8820}
8821
8822// A focused & mirrored window remains focused until the window and its mirror both become
8823// invisible.
8824TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8825 setFocusedWindow(mMirror);
8826
8827 // window gets focused
8828 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008830 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008831 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008833 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008834 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8835
8836 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008837 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008838
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008840 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008841 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008843 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008844 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8845
8846 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008847 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008848
8849 // window loses focus only after all windows associated with the token become invisible.
8850 mWindow->consumeFocusEvent(false);
8851
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008852 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008853 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008854 mWindow->assertNoEvents();
8855}
8856
8857// A focused & mirrored window remains focused until both windows are removed.
8858TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8859 setFocusedWindow(mMirror);
8860
8861 // window gets focused
8862 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008864 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008865 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008867 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008868 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8869
8870 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008871 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008872
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008874 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008875 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008877 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008878 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8879
8880 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008881 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008882 mWindow->consumeFocusEvent(false);
8883
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008884 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008885 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008886 mWindow->assertNoEvents();
8887}
8888
8889// Focus request can be pending until one window becomes visible.
8890TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8891 // Request focus on an invisible mirror.
8892 mWindow->setVisible(false);
8893 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008894 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008895 setFocusedWindow(mMirror);
8896
8897 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008899 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8900 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008901
8902 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008903 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008904
8905 // window gets focused
8906 mWindow->consumeFocusEvent(true);
8907 // window gets the pending key event
8908 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8909}
Prabir Pradhan99987712020-11-10 18:43:05 -08008910
8911class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8912protected:
8913 std::shared_ptr<FakeApplicationHandle> mApp;
8914 sp<FakeWindowHandle> mWindow;
8915 sp<FakeWindowHandle> mSecondWindow;
8916
8917 void SetUp() override {
8918 InputDispatcherTest::SetUp();
8919 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008920 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008921 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008922 mSecondWindow =
8923 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008924 mSecondWindow->setFocusable(true);
8925
8926 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008927 mDispatcher->onWindowInfosChanged(
8928 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008929
8930 setFocusedWindow(mWindow);
8931 mWindow->consumeFocusEvent(true);
8932 }
8933
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008934 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008935 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008936 }
8937
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008938 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8939 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008940 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008941 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8942 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008943 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008944 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008945 }
8946};
8947
8948TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8949 // Ensure that capture cannot be obtained for unfocused windows.
8950 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8951 mFakePolicy->assertSetPointerCaptureNotCalled();
8952 mSecondWindow->assertNoEvents();
8953
8954 // Ensure that capture can be enabled from the focus window.
8955 requestAndVerifyPointerCapture(mWindow, true);
8956
8957 // Ensure that capture cannot be disabled from a window that does not have capture.
8958 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8959 mFakePolicy->assertSetPointerCaptureNotCalled();
8960
8961 // Ensure that capture can be disabled from the window with capture.
8962 requestAndVerifyPointerCapture(mWindow, false);
8963}
8964
8965TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008966 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008967
8968 setFocusedWindow(mSecondWindow);
8969
8970 // Ensure that the capture disabled event was sent first.
8971 mWindow->consumeCaptureEvent(false);
8972 mWindow->consumeFocusEvent(false);
8973 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008974 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008975
8976 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008977 notifyPointerCaptureChanged({});
8978 notifyPointerCaptureChanged(request);
8979 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008980 mWindow->assertNoEvents();
8981 mSecondWindow->assertNoEvents();
8982 mFakePolicy->assertSetPointerCaptureNotCalled();
8983}
8984
8985TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008986 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008987
8988 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008989 notifyPointerCaptureChanged({});
8990 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008991
8992 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008993 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008994 mWindow->consumeCaptureEvent(false);
8995 mWindow->assertNoEvents();
8996}
8997
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008998TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8999 requestAndVerifyPointerCapture(mWindow, true);
9000
9001 // The first window loses focus.
9002 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009003 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009004 mWindow->consumeCaptureEvent(false);
9005
9006 // Request Pointer Capture from the second window before the notification from InputReader
9007 // arrives.
9008 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009009 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009010
9011 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009012 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009013
9014 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009015 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009016
9017 mSecondWindow->consumeFocusEvent(true);
9018 mSecondWindow->consumeCaptureEvent(true);
9019}
9020
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009021TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9022 // App repeatedly enables and disables capture.
9023 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9024 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9025 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9026 mFakePolicy->assertSetPointerCaptureCalled(false);
9027 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9028 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9029
9030 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9031 // first request is now stale, this should do nothing.
9032 notifyPointerCaptureChanged(firstRequest);
9033 mWindow->assertNoEvents();
9034
9035 // InputReader notifies that the second request was enabled.
9036 notifyPointerCaptureChanged(secondRequest);
9037 mWindow->consumeCaptureEvent(true);
9038}
9039
Prabir Pradhan7092e262022-05-03 16:51:09 +00009040TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9041 requestAndVerifyPointerCapture(mWindow, true);
9042
9043 // App toggles pointer capture off and on.
9044 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9045 mFakePolicy->assertSetPointerCaptureCalled(false);
9046
9047 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9048 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9049
9050 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9051 // preceding "disable" request.
9052 notifyPointerCaptureChanged(enableRequest);
9053
9054 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9055 // any notifications.
9056 mWindow->assertNoEvents();
9057}
9058
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009059/**
9060 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9061 * mouse movements don't affect the previous mouse hovering state.
9062 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9063 * HOVER_MOVE events).
9064 */
9065TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9066 // Mouse hover on the window
9067 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9068 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9069 .build());
9070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9071 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9072 .build());
9073
9074 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9075 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9076
9077 // Start pointer capture
9078 requestAndVerifyPointerCapture(mWindow, true);
9079
9080 // Send some relative mouse movements and receive them in the window.
9081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9082 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9083 .build());
9084 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9085 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9086
9087 // Stop pointer capture
9088 requestAndVerifyPointerCapture(mWindow, false);
9089
9090 // Continue hovering on the window
9091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9092 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9093 .build());
9094 mWindow->consumeMotionEvent(
9095 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9096
9097 mWindow->assertNoEvents();
9098}
9099
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009100class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9101protected:
9102 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009103
9104 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9105 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9106
9107 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9108 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9109
9110 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9111 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9112 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9113 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9114 MAXIMUM_OBSCURING_OPACITY);
9115
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009116 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9117 static constexpr gui::Uid APP_B_UID{10002};
9118 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009119
9120 sp<FakeWindowHandle> mTouchWindow;
9121
9122 virtual void SetUp() override {
9123 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009124 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009125 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9126 }
9127
9128 virtual void TearDown() override {
9129 InputDispatcherTest::TearDown();
9130 mTouchWindow.clear();
9131 }
9132
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009133 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009134 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009135 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009136 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009137 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009138 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009139 return window;
9140 }
9141
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009142 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009143 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9144 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009145 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009146 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009147 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009148 return window;
9149 }
9150
9151 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009152 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9153 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9154 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009155 }
9156};
9157
9158TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009159 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009160 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009161 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009162
9163 touch();
9164
9165 mTouchWindow->assertNoEvents();
9166}
9167
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009168TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009169 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9170 const sp<FakeWindowHandle>& w =
9171 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009172 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009173
9174 touch();
9175
9176 mTouchWindow->assertNoEvents();
9177}
9178
9179TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009180 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9181 const sp<FakeWindowHandle>& w =
9182 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009183 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009184
9185 touch();
9186
9187 w->assertNoEvents();
9188}
9189
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009190TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009191 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009192 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009193
9194 touch();
9195
9196 mTouchWindow->consumeAnyMotionDown();
9197}
9198
9199TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009200 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009201 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009202 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009203 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009204
9205 touch({PointF{100, 100}});
9206
9207 mTouchWindow->consumeAnyMotionDown();
9208}
9209
9210TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009211 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009212 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009213 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009214
9215 touch();
9216
9217 mTouchWindow->consumeAnyMotionDown();
9218}
9219
9220TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9221 const sp<FakeWindowHandle>& w =
9222 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009223 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009224
9225 touch();
9226
9227 mTouchWindow->consumeAnyMotionDown();
9228}
9229
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009230TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9231 const sp<FakeWindowHandle>& w =
9232 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009233 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009234
9235 touch();
9236
9237 w->assertNoEvents();
9238}
9239
9240/**
9241 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9242 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9243 * window, the occluding window will still receive ACTION_OUTSIDE event.
9244 */
9245TEST_F(InputDispatcherUntrustedTouchesTest,
9246 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9247 const sp<FakeWindowHandle>& w =
9248 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009249 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009250 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009251
9252 touch();
9253
9254 w->consumeMotionOutside();
9255}
9256
9257TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9258 const sp<FakeWindowHandle>& w =
9259 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009260 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009261 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009262
9263 touch();
9264
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009265 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009266}
9267
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009268TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009269 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009270 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9271 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009272 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009273
9274 touch();
9275
9276 mTouchWindow->consumeAnyMotionDown();
9277}
9278
9279TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9280 const sp<FakeWindowHandle>& w =
9281 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9282 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009283 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009284
9285 touch();
9286
9287 mTouchWindow->consumeAnyMotionDown();
9288}
9289
9290TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009291 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009292 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9293 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009294 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009295
9296 touch();
9297
9298 mTouchWindow->assertNoEvents();
9299}
9300
9301TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9302 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9303 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009304 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9305 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009306 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009307 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9308 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009309 mDispatcher->onWindowInfosChanged(
9310 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009311
9312 touch();
9313
9314 mTouchWindow->assertNoEvents();
9315}
9316
9317TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9318 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9319 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009320 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9321 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009322 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009323 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9324 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009325 mDispatcher->onWindowInfosChanged(
9326 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009327
9328 touch();
9329
9330 mTouchWindow->consumeAnyMotionDown();
9331}
9332
9333TEST_F(InputDispatcherUntrustedTouchesTest,
9334 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9335 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009336 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9337 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009338 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009339 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9340 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009341 mDispatcher->onWindowInfosChanged(
9342 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009343
9344 touch();
9345
9346 mTouchWindow->consumeAnyMotionDown();
9347}
9348
9349TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9350 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009351 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9352 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009353 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009354 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9355 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009356 mDispatcher->onWindowInfosChanged(
9357 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009358
9359 touch();
9360
9361 mTouchWindow->assertNoEvents();
9362}
9363
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009364TEST_F(InputDispatcherUntrustedTouchesTest,
9365 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9366 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009367 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9368 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009369 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009370 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9371 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009372 mDispatcher->onWindowInfosChanged(
9373 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009374
9375 touch();
9376
9377 mTouchWindow->assertNoEvents();
9378}
9379
9380TEST_F(InputDispatcherUntrustedTouchesTest,
9381 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9382 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009383 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9384 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009385 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009386 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9387 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009388 mDispatcher->onWindowInfosChanged(
9389 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009390
9391 touch();
9392
9393 mTouchWindow->consumeAnyMotionDown();
9394}
9395
9396TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9397 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009398 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9399 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009400 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009401
9402 touch();
9403
9404 mTouchWindow->consumeAnyMotionDown();
9405}
9406
9407TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9408 const sp<FakeWindowHandle>& w =
9409 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009410 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009411
9412 touch();
9413
9414 mTouchWindow->consumeAnyMotionDown();
9415}
9416
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009417TEST_F(InputDispatcherUntrustedTouchesTest,
9418 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9419 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9420 const sp<FakeWindowHandle>& w =
9421 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009422 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009423
9424 touch();
9425
9426 mTouchWindow->assertNoEvents();
9427}
9428
9429TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9430 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9431 const sp<FakeWindowHandle>& w =
9432 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009433 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009434
9435 touch();
9436
9437 mTouchWindow->consumeAnyMotionDown();
9438}
9439
9440TEST_F(InputDispatcherUntrustedTouchesTest,
9441 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9442 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9443 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009444 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9445 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009446 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009447
9448 touch();
9449
9450 mTouchWindow->consumeAnyMotionDown();
9451}
9452
9453TEST_F(InputDispatcherUntrustedTouchesTest,
9454 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9455 const sp<FakeWindowHandle>& w1 =
9456 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9457 OPACITY_BELOW_THRESHOLD);
9458 const sp<FakeWindowHandle>& w2 =
9459 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9460 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009461 mDispatcher->onWindowInfosChanged(
9462 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009463
9464 touch();
9465
9466 mTouchWindow->assertNoEvents();
9467}
9468
9469/**
9470 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9471 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9472 * (which alone would result in allowing touches) does not affect the blocking behavior.
9473 */
9474TEST_F(InputDispatcherUntrustedTouchesTest,
9475 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9476 const sp<FakeWindowHandle>& wB =
9477 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9478 OPACITY_BELOW_THRESHOLD);
9479 const sp<FakeWindowHandle>& wC =
9480 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9481 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009482 mDispatcher->onWindowInfosChanged(
9483 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009484
9485 touch();
9486
9487 mTouchWindow->assertNoEvents();
9488}
9489
9490/**
9491 * This test is testing that a window from a different UID but with same application token doesn't
9492 * block the touch. Apps can share the application token for close UI collaboration for example.
9493 */
9494TEST_F(InputDispatcherUntrustedTouchesTest,
9495 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9496 const sp<FakeWindowHandle>& w =
9497 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9498 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009499 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009500
9501 touch();
9502
9503 mTouchWindow->consumeAnyMotionDown();
9504}
9505
arthurhungb89ccb02020-12-30 16:19:01 +08009506class InputDispatcherDragTests : public InputDispatcherTest {
9507protected:
9508 std::shared_ptr<FakeApplicationHandle> mApp;
9509 sp<FakeWindowHandle> mWindow;
9510 sp<FakeWindowHandle> mSecondWindow;
9511 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009512 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009513 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9514 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009515
9516 void SetUp() override {
9517 InputDispatcherTest::SetUp();
9518 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009519 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009520 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009521
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009522 mSecondWindow =
9523 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009524 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009525
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009526 mSpyWindow =
9527 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009528 mSpyWindow->setSpy(true);
9529 mSpyWindow->setTrustedOverlay(true);
9530 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9531
arthurhungb89ccb02020-12-30 16:19:01 +08009532 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009533 mDispatcher->onWindowInfosChanged(
9534 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9535 {},
9536 0,
9537 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009538 }
9539
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009540 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9541 switch (fromSource) {
9542 case AINPUT_SOURCE_TOUCHSCREEN:
9543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009545 ADISPLAY_ID_DEFAULT, {50, 50}))
9546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9547 break;
9548 case AINPUT_SOURCE_STYLUS:
9549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009550 injectMotionEvent(*mDispatcher,
9551 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9552 AINPUT_SOURCE_STYLUS)
9553 .buttonState(
9554 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9555 .pointer(PointerBuilder(0, ToolType::STYLUS)
9556 .x(50)
9557 .y(50))
9558 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009559 break;
9560 case AINPUT_SOURCE_MOUSE:
9561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009562 injectMotionEvent(*mDispatcher,
9563 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9564 AINPUT_SOURCE_MOUSE)
9565 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9566 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9567 ToolType::MOUSE)
9568 .x(50)
9569 .y(50))
9570 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009571 break;
9572 default:
9573 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9574 }
arthurhungb89ccb02020-12-30 16:19:01 +08009575
9576 // Window should receive motion event.
9577 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009578 // Spy window should also receive motion event
9579 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009580 }
9581
9582 // Start performing drag, we will create a drag window and transfer touch to it.
9583 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9584 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009585 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009586 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009587 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009588 }
arthurhungb89ccb02020-12-30 16:19:01 +08009589
9590 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009591 mDragWindow =
9592 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009593 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009594 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9595 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9596 {},
9597 0,
9598 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009599
9600 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009601 bool transferred =
9602 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009603 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009604 if (transferred) {
9605 mWindow->consumeMotionCancel();
9606 mDragWindow->consumeMotionDown();
9607 }
9608 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009609 }
9610};
9611
9612TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009613 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009614
9615 // Move on window.
9616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009617 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009618 ADISPLAY_ID_DEFAULT, {50, 50}))
9619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9620 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9621 mWindow->consumeDragEvent(false, 50, 50);
9622 mSecondWindow->assertNoEvents();
9623
9624 // Move to another window.
9625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009626 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009627 ADISPLAY_ID_DEFAULT, {150, 50}))
9628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9629 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9630 mWindow->consumeDragEvent(true, 150, 50);
9631 mSecondWindow->consumeDragEvent(false, 50, 50);
9632
9633 // Move back to original window.
9634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009635 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009636 ADISPLAY_ID_DEFAULT, {50, 50}))
9637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9638 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9639 mWindow->consumeDragEvent(false, 50, 50);
9640 mSecondWindow->consumeDragEvent(true, -50, 50);
9641
9642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009643 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9644 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9646 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9647 mWindow->assertNoEvents();
9648 mSecondWindow->assertNoEvents();
9649}
9650
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009651TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009652 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009653
9654 // No cancel event after drag start
9655 mSpyWindow->assertNoEvents();
9656
9657 const MotionEvent secondFingerDownEvent =
9658 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9659 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009660 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9661 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009662 .build();
9663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009664 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009665 InputEventInjectionSync::WAIT_FOR_RESULT))
9666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9667
9668 // Receives cancel for first pointer after next pointer down
9669 mSpyWindow->consumeMotionCancel();
9670 mSpyWindow->consumeMotionDown();
9671
9672 mSpyWindow->assertNoEvents();
9673}
9674
arthurhungf452d0b2021-01-06 00:19:52 +08009675TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009676 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009677
9678 // Move on window.
9679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009680 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009681 ADISPLAY_ID_DEFAULT, {50, 50}))
9682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9683 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9684 mWindow->consumeDragEvent(false, 50, 50);
9685 mSecondWindow->assertNoEvents();
9686
9687 // Move to another window.
9688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009689 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009690 ADISPLAY_ID_DEFAULT, {150, 50}))
9691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9692 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9693 mWindow->consumeDragEvent(true, 150, 50);
9694 mSecondWindow->consumeDragEvent(false, 50, 50);
9695
9696 // drop to another window.
9697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009698 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009699 {150, 50}))
9700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9701 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009702 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009703 mWindow->assertNoEvents();
9704 mSecondWindow->assertNoEvents();
9705}
9706
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009707TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9708 startDrag();
9709
9710 // No cancel event after drag start
9711 mSpyWindow->assertNoEvents();
9712
9713 const MotionEvent secondFingerDownEvent =
9714 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9715 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9716 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9717 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9718 .build();
9719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9720 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9721 InputEventInjectionSync::WAIT_FOR_RESULT))
9722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9723
9724 // Receives cancel for first pointer after next pointer down
9725 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9726 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9727 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9728
9729 mSpyWindow->assertNoEvents();
9730
9731 // Spy window calls pilfer pointers
9732 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9733 mDragWindow->assertNoEvents();
9734
9735 const MotionEvent firstFingerMoveEvent =
9736 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9737 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9738 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9739 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9740 .build();
9741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9742 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9743 InputEventInjectionSync::WAIT_FOR_RESULT))
9744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9745
9746 // Drag window should still receive the new event
9747 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9748 mDragWindow->assertNoEvents();
9749}
9750
arthurhung6d4bed92021-03-17 11:59:33 +08009751TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009752 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009753
9754 // Move on window and keep button pressed.
9755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009756 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009757 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9758 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009759 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009760 .build()))
9761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9762 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9763 mWindow->consumeDragEvent(false, 50, 50);
9764 mSecondWindow->assertNoEvents();
9765
9766 // Move to another window and release button, expect to drop item.
9767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009768 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009769 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9770 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009771 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009772 .build()))
9773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9774 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9775 mWindow->assertNoEvents();
9776 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009777 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009778
9779 // nothing to the window.
9780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009781 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009782 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9783 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009784 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009785 .build()))
9786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9787 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9788 mWindow->assertNoEvents();
9789 mSecondWindow->assertNoEvents();
9790}
9791
Arthur Hung54745652022-04-20 07:17:41 +00009792TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009793 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009794
9795 // Set second window invisible.
9796 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009797 mDispatcher->onWindowInfosChanged(
9798 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009799
9800 // Move on window.
9801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009802 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009803 ADISPLAY_ID_DEFAULT, {50, 50}))
9804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9805 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9806 mWindow->consumeDragEvent(false, 50, 50);
9807 mSecondWindow->assertNoEvents();
9808
9809 // Move to another window.
9810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009811 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009812 ADISPLAY_ID_DEFAULT, {150, 50}))
9813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9814 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9815 mWindow->consumeDragEvent(true, 150, 50);
9816 mSecondWindow->assertNoEvents();
9817
9818 // drop to another window.
9819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009820 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009821 {150, 50}))
9822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9823 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009824 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009825 mWindow->assertNoEvents();
9826 mSecondWindow->assertNoEvents();
9827}
9828
Arthur Hung54745652022-04-20 07:17:41 +00009829TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009830 // Ensure window could track pointerIds if it didn't support split touch.
9831 mWindow->setPreventSplitting(true);
9832
Arthur Hung54745652022-04-20 07:17:41 +00009833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009834 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009835 {50, 50}))
9836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9837 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9838
9839 const MotionEvent secondFingerDownEvent =
9840 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9841 .displayId(ADISPLAY_ID_DEFAULT)
9842 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009843 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9844 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009845 .build();
9846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009847 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009848 InputEventInjectionSync::WAIT_FOR_RESULT))
9849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009850 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009851
9852 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009853 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009854}
9855
9856TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9857 // First down on second window.
9858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009859 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009860 {150, 50}))
9861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9862
9863 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9864
9865 // Second down on first window.
9866 const MotionEvent secondFingerDownEvent =
9867 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9868 .displayId(ADISPLAY_ID_DEFAULT)
9869 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009870 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9871 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009872 .build();
9873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009874 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009875 InputEventInjectionSync::WAIT_FOR_RESULT))
9876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9877 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9878
9879 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009880 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009881
9882 // Move on window.
9883 const MotionEvent secondFingerMoveEvent =
9884 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9885 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009886 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9887 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009888 .build();
9889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009890 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009891 InputEventInjectionSync::WAIT_FOR_RESULT));
9892 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9893 mWindow->consumeDragEvent(false, 50, 50);
9894 mSecondWindow->consumeMotionMove();
9895
9896 // Release the drag pointer should perform drop.
9897 const MotionEvent secondFingerUpEvent =
9898 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9899 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009900 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9901 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009902 .build();
9903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009904 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009905 InputEventInjectionSync::WAIT_FOR_RESULT));
9906 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009907 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009908 mWindow->assertNoEvents();
9909 mSecondWindow->consumeMotionMove();
9910}
9911
Arthur Hung3915c1f2022-05-31 07:17:17 +00009912TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009913 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009914
9915 // Update window of second display.
9916 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009917 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009918 mDispatcher->onWindowInfosChanged(
9919 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9920 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9921 {},
9922 0,
9923 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009924
9925 // Let second display has a touch state.
9926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009927 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009928 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9929 AINPUT_SOURCE_TOUCHSCREEN)
9930 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009931 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009932 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009933 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009934 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009935 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009936 mDispatcher->onWindowInfosChanged(
9937 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9938 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9939 {},
9940 0,
9941 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009942
9943 // Move on window.
9944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009945 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009946 ADISPLAY_ID_DEFAULT, {50, 50}))
9947 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9948 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9949 mWindow->consumeDragEvent(false, 50, 50);
9950 mSecondWindow->assertNoEvents();
9951
9952 // Move to another window.
9953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009954 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009955 ADISPLAY_ID_DEFAULT, {150, 50}))
9956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9957 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9958 mWindow->consumeDragEvent(true, 150, 50);
9959 mSecondWindow->consumeDragEvent(false, 50, 50);
9960
9961 // drop to another window.
9962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009963 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009964 {150, 50}))
9965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9966 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009967 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009968 mWindow->assertNoEvents();
9969 mSecondWindow->assertNoEvents();
9970}
9971
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009972TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9973 startDrag(true, AINPUT_SOURCE_MOUSE);
9974 // Move on window.
9975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009976 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009977 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9978 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009979 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009980 .x(50)
9981 .y(50))
9982 .build()))
9983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9984 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9985 mWindow->consumeDragEvent(false, 50, 50);
9986 mSecondWindow->assertNoEvents();
9987
9988 // Move to another window.
9989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009990 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009991 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9992 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009993 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009994 .x(150)
9995 .y(50))
9996 .build()))
9997 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9998 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9999 mWindow->consumeDragEvent(true, 150, 50);
10000 mSecondWindow->consumeDragEvent(false, 50, 50);
10001
10002 // drop to another window.
10003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010004 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010005 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10006 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010007 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010008 .x(150)
10009 .y(50))
10010 .build()))
10011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10012 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010013 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010014 mWindow->assertNoEvents();
10015 mSecondWindow->assertNoEvents();
10016}
10017
Linnan Li5af92f92023-07-14 14:36:22 +080010018/**
10019 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10020 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10021 */
10022TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10023 // Down on second window
10024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10025 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10026 {150, 50}))
10027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10028
10029 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10030 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10031
10032 // Down on first window
10033 const MotionEvent secondFingerDownEvent =
10034 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10035 .displayId(ADISPLAY_ID_DEFAULT)
10036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10038 .build();
10039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10040 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10041 InputEventInjectionSync::WAIT_FOR_RESULT))
10042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10043 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10044 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10045 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10046
10047 // Start drag on first window
10048 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10049
10050 // Trigger cancel
10051 mDispatcher->cancelCurrentTouch();
10052 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10053 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10054 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10055
10056 ASSERT_TRUE(mDispatcher->waitForIdle());
10057 // The D&D finished with nullptr
10058 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10059
10060 // Remove drag window
10061 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10062
10063 // Inject a simple gesture, ensure dispatcher not crashed
10064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10065 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10066 PointF{50, 50}))
10067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10068 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10069
10070 const MotionEvent moveEvent =
10071 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10072 .displayId(ADISPLAY_ID_DEFAULT)
10073 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10074 .build();
10075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10076 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10077 InputEventInjectionSync::WAIT_FOR_RESULT))
10078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10079 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10080
10081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10082 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10083 {50, 50}))
10084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10085 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10086}
10087
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010088TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10089 // Start hovering over the window.
10090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10091 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10092 ADISPLAY_ID_DEFAULT, {50, 50}));
10093
10094 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10095 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10096
10097 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10098 << "Drag and drop should not work with a hovering pointer";
10099}
10100
Vishnu Nair062a8672021-09-03 16:07:44 -070010101class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10102
10103TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010105 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10106 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010107 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010108 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10109 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010110 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010111 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010112 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010113
10114 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010115 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010116 window->assertNoEvents();
10117
Prabir Pradhan678438e2023-04-13 19:32:51 +000010118 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10119 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010120 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10121 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010122 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010123 window->assertNoEvents();
10124
10125 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010126 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010127 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010128
Prabir Pradhan678438e2023-04-13 19:32:51 +000010129 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010130 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10131
Prabir Pradhan678438e2023-04-13 19:32:51 +000010132 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10133 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010134 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10135 window->assertNoEvents();
10136}
10137
10138TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10139 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10140 std::make_shared<FakeApplicationHandle>();
10141 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010142 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10143 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010144 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010145 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010146 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010148 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10149 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010150 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010151 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010152 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10153 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010154 mDispatcher->onWindowInfosChanged(
10155 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010156 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010157 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010158
10159 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010160 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010161 window->assertNoEvents();
10162
Prabir Pradhan678438e2023-04-13 19:32:51 +000010163 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10164 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010165 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10166 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010167 window->assertNoEvents();
10168
10169 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010170 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010171 mDispatcher->onWindowInfosChanged(
10172 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010173
Prabir Pradhan678438e2023-04-13 19:32:51 +000010174 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010175 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10176
Prabir Pradhan678438e2023-04-13 19:32:51 +000010177 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010179 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10180 window->assertNoEvents();
10181}
10182
10183TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10184 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10185 std::make_shared<FakeApplicationHandle>();
10186 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010187 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10188 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010189 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010190 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010191 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010193 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10194 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010195 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010196 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010197 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10198 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010199 mDispatcher->onWindowInfosChanged(
10200 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010201 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010202 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010203
10204 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010205 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010206 window->assertNoEvents();
10207
Prabir Pradhan678438e2023-04-13 19:32:51 +000010208 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10209 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010210 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10211 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010212 window->assertNoEvents();
10213
10214 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010215 mDispatcher->onWindowInfosChanged(
10216 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010217
Prabir Pradhan678438e2023-04-13 19:32:51 +000010218 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010219 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10220
Prabir Pradhan678438e2023-04-13 19:32:51 +000010221 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10222 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010223 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10224 window->assertNoEvents();
10225}
10226
Antonio Kantekf16f2832021-09-28 04:39:20 +000010227class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10228protected:
10229 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010230 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010231 sp<FakeWindowHandle> mWindow;
10232 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010233 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010234
10235 void SetUp() override {
10236 InputDispatcherTest::SetUp();
10237
10238 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010239 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010240 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010241 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010242 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010243 mSecondWindow =
10244 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010245 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010246 mThirdWindow =
10247 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10248 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10249 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010250
10251 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010252 mDispatcher->onWindowInfosChanged(
10253 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10254 {},
10255 0,
10256 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010257 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010258 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010259
Antonio Kantek15beb512022-06-13 22:35:41 +000010260 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010261 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010262 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010263 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10264 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010265 mThirdWindow->assertNoEvents();
10266 }
10267
10268 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10269 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010270 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010271 SECOND_DISPLAY_ID)) {
10272 mWindow->assertNoEvents();
10273 mSecondWindow->assertNoEvents();
10274 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010275 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010276 }
10277
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010278 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010279 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010280 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10281 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010282 mWindow->consumeTouchModeEvent(inTouchMode);
10283 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010284 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010285 }
10286};
10287
Antonio Kantek26defcf2022-02-08 01:12:27 +000010288TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010289 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010290 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10291 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010292 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010293}
10294
Antonio Kantek26defcf2022-02-08 01:12:27 +000010295TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10296 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010297 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010298 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010299 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010300 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010301 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010302 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010303 mWindow->assertNoEvents();
10304 mSecondWindow->assertNoEvents();
10305}
10306
10307TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10308 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010309 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010310 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010311 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010312 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010313 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010314}
10315
Antonio Kantekf16f2832021-09-28 04:39:20 +000010316TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010317 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010318 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10319 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010320 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010321 mWindow->assertNoEvents();
10322 mSecondWindow->assertNoEvents();
10323}
10324
Antonio Kantek15beb512022-06-13 22:35:41 +000010325TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10326 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10327 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10328 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010329 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010330 mWindow->assertNoEvents();
10331 mSecondWindow->assertNoEvents();
10332 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10333}
10334
Antonio Kantek48710e42022-03-24 14:19:30 -070010335TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10336 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10338 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010339 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10340 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10341
10342 // Then remove focus.
10343 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010344 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010345
10346 // Assert that caller can switch touch mode by owning one of the last interacted window.
10347 const WindowInfo& windowInfo = *mWindow->getInfo();
10348 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10349 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010350 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010351}
10352
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010353class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10354public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010355 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010356 std::shared_ptr<FakeApplicationHandle> application =
10357 std::make_shared<FakeApplicationHandle>();
10358 std::string name = "Fake Spy ";
10359 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010360 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10361 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010362 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010363 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010364 return spy;
10365 }
10366
10367 sp<FakeWindowHandle> createForeground() {
10368 std::shared_ptr<FakeApplicationHandle> application =
10369 std::make_shared<FakeApplicationHandle>();
10370 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010371 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10372 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010373 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010374 return window;
10375 }
10376
10377private:
10378 int mSpyCount{0};
10379};
10380
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010381using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010382/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010383 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10384 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010385TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010386 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010387 ScopedSilentDeath _silentDeath;
10388
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010389 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010390 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010391 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010392 ".* not a trusted overlay");
10393}
10394
10395/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010396 * Input injection into a display with a spy window but no foreground windows should succeed.
10397 */
10398TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010399 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010400 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010401
10402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010403 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10405 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10406}
10407
10408/**
10409 * Verify the order in which different input windows receive events. The touched foreground window
10410 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10411 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10412 * receive events before ones belows it.
10413 *
10414 * Here, we set up a scenario with four windows in the following Z order from the top:
10415 * spy1, spy2, window, spy3.
10416 * We then inject an event and verify that the foreground "window" receives it first, followed by
10417 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10418 * window.
10419 */
10420TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10421 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010422 auto spy1 = createSpy();
10423 auto spy2 = createSpy();
10424 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010425 mDispatcher->onWindowInfosChanged(
10426 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010427 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10428 const size_t numChannels = channels.size();
10429
Michael Wright8e9a8562022-02-09 13:44:29 +000010430 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010431 if (!epollFd.ok()) {
10432 FAIL() << "Failed to create epoll fd";
10433 }
10434
10435 for (size_t i = 0; i < numChannels; i++) {
10436 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10437 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10438 FAIL() << "Failed to add fd to epoll";
10439 }
10440 }
10441
10442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010443 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10445
10446 std::vector<size_t> eventOrder;
10447 std::vector<struct epoll_event> events(numChannels);
10448 for (;;) {
10449 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10450 (100ms).count());
10451 if (nFds < 0) {
10452 FAIL() << "Failed to call epoll_wait";
10453 }
10454 if (nFds == 0) {
10455 break; // epoll_wait timed out
10456 }
10457 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010458 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010459 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010460 channels[i]->consumeMotionDown();
10461 }
10462 }
10463
10464 // Verify the order in which the events were received.
10465 EXPECT_EQ(3u, eventOrder.size());
10466 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10467 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10468 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10469}
10470
10471/**
10472 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10473 */
10474TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10475 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010476 auto spy = createSpy();
10477 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010478 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010479
10480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010481 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10483 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10484 spy->assertNoEvents();
10485}
10486
10487/**
10488 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10489 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10490 * to the window.
10491 */
10492TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10493 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010494 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010495 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010496 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010497
10498 // Inject an event outside the spy window's touchable region.
10499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010500 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010501 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10502 window->consumeMotionDown();
10503 spy->assertNoEvents();
10504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010505 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10507 window->consumeMotionUp();
10508 spy->assertNoEvents();
10509
10510 // Inject an event inside the spy window's touchable region.
10511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010512 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010513 {5, 10}))
10514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10515 window->consumeMotionDown();
10516 spy->consumeMotionDown();
10517}
10518
10519/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010520 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010521 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010522 */
10523TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10524 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010525 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010526 auto spy = createSpy();
10527 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010528 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010529 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010530 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010531
10532 // Inject an event outside the spy window's frame and touchable region.
10533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010534 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010535 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010536 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10537 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010538 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010539}
10540
10541/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010542 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10543 * pointers that are down within its bounds.
10544 */
10545TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10546 auto windowLeft = createForeground();
10547 windowLeft->setFrame({0, 0, 100, 200});
10548 auto windowRight = createForeground();
10549 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010550 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010551 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010552 mDispatcher->onWindowInfosChanged(
10553 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010554
10555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010556 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010557 {50, 50}))
10558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10559 windowLeft->consumeMotionDown();
10560 spy->consumeMotionDown();
10561
10562 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010563 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010564 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010565 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10566 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010567 .build();
10568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010569 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010570 InputEventInjectionSync::WAIT_FOR_RESULT))
10571 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10572 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010573 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010574}
10575
10576/**
10577 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10578 * the spy should receive the second pointer with ACTION_DOWN.
10579 */
10580TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10581 auto window = createForeground();
10582 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010583 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010584 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010585 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010586
10587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010588 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010589 {50, 50}))
10590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10591 window->consumeMotionDown();
10592 spyRight->assertNoEvents();
10593
10594 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010595 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010596 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010597 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10598 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010599 .build();
10600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010601 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010602 InputEventInjectionSync::WAIT_FOR_RESULT))
10603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010604 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010605 spyRight->consumeMotionDown();
10606}
10607
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010608/**
10609 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10610 * windows should be allowed to control split touch.
10611 */
10612TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010613 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010614 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010615 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010616 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010617
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010618 auto window = createForeground();
10619 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010620
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010621 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010622
10623 // First finger down, no window touched.
10624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010625 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010626 {100, 200}))
10627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10628 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10629 window->assertNoEvents();
10630
10631 // Second finger down on window, the window should receive touch down.
10632 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010633 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010634 .displayId(ADISPLAY_ID_DEFAULT)
10635 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010636 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10637 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010638 .build();
10639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010640 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010641 InputEventInjectionSync::WAIT_FOR_RESULT))
10642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10643
10644 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010645 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010646}
10647
10648/**
10649 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10650 * do not receive key events.
10651 */
10652TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010653 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010654 spy->setFocusable(false);
10655
10656 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010657 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010658 setFocusedWindow(window);
10659 window->consumeFocusEvent(true);
10660
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010662 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10663 window->consumeKeyDown(ADISPLAY_ID_NONE);
10664
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010666 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10667 window->consumeKeyUp(ADISPLAY_ID_NONE);
10668
10669 spy->assertNoEvents();
10670}
10671
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010672using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10673
10674/**
10675 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10676 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10677 */
10678TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10679 auto window = createForeground();
10680 auto spy1 = createSpy();
10681 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010682 mDispatcher->onWindowInfosChanged(
10683 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010684
10685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010687 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10688 window->consumeMotionDown();
10689 spy1->consumeMotionDown();
10690 spy2->consumeMotionDown();
10691
10692 // Pilfer pointers from the second spy window.
10693 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10694 spy2->assertNoEvents();
10695 spy1->consumeMotionCancel();
10696 window->consumeMotionCancel();
10697
10698 // The rest of the gesture should only be sent to the second spy window.
10699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010700 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010701 ADISPLAY_ID_DEFAULT))
10702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10703 spy2->consumeMotionMove();
10704 spy1->assertNoEvents();
10705 window->assertNoEvents();
10706}
10707
10708/**
10709 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10710 * in the middle of the gesture.
10711 */
10712TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10713 auto window = createForeground();
10714 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010715 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010716
10717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010718 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10720 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10721 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10722
10723 window->releaseChannel();
10724
10725 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10726
10727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010728 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10730 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10731}
10732
10733/**
10734 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10735 * the spy, but not to any other windows.
10736 */
10737TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10738 auto spy = createSpy();
10739 auto window = createForeground();
10740
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010741 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010742
10743 // First finger down on the window and the spy.
10744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010745 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010746 {100, 200}))
10747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10748 spy->consumeMotionDown();
10749 window->consumeMotionDown();
10750
10751 // Spy window pilfers the pointers.
10752 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10753 window->consumeMotionCancel();
10754
10755 // Second finger down on the window and spy, but the window should not receive the pointer down.
10756 const MotionEvent secondFingerDownEvent =
10757 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10758 .displayId(ADISPLAY_ID_DEFAULT)
10759 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010760 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10761 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010762 .build();
10763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010764 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010765 InputEventInjectionSync::WAIT_FOR_RESULT))
10766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10767
Harry Cutts33476232023-01-30 19:57:29 +000010768 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010769
10770 // Third finger goes down outside all windows, so injection should fail.
10771 const MotionEvent thirdFingerDownEvent =
10772 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10773 .displayId(ADISPLAY_ID_DEFAULT)
10774 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010775 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10776 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10777 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010778 .build();
10779 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010780 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010781 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010782 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010783
10784 spy->assertNoEvents();
10785 window->assertNoEvents();
10786}
10787
10788/**
10789 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10790 */
10791TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10792 auto spy = createSpy();
10793 spy->setFrame(Rect(0, 0, 100, 100));
10794 auto window = createForeground();
10795 window->setFrame(Rect(0, 0, 200, 200));
10796
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010797 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010798
10799 // First finger down on the window only
10800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010802 {150, 150}))
10803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10804 window->consumeMotionDown();
10805
10806 // Second finger down on the spy and window
10807 const MotionEvent secondFingerDownEvent =
10808 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10809 .displayId(ADISPLAY_ID_DEFAULT)
10810 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010811 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10812 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010813 .build();
10814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010815 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010816 InputEventInjectionSync::WAIT_FOR_RESULT))
10817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10818 spy->consumeMotionDown();
10819 window->consumeMotionPointerDown(1);
10820
10821 // Third finger down on the spy and window
10822 const MotionEvent thirdFingerDownEvent =
10823 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10824 .displayId(ADISPLAY_ID_DEFAULT)
10825 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010826 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10827 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10828 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010829 .build();
10830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010831 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010832 InputEventInjectionSync::WAIT_FOR_RESULT))
10833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10834 spy->consumeMotionPointerDown(1);
10835 window->consumeMotionPointerDown(2);
10836
10837 // Spy window pilfers the pointers.
10838 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010839 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10840 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010841
10842 spy->assertNoEvents();
10843 window->assertNoEvents();
10844}
10845
10846/**
10847 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10848 * other windows should be canceled. If this results in the cancellation of all pointers for some
10849 * window, then that window should receive ACTION_CANCEL.
10850 */
10851TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10852 auto spy = createSpy();
10853 spy->setFrame(Rect(0, 0, 100, 100));
10854 auto window = createForeground();
10855 window->setFrame(Rect(0, 0, 200, 200));
10856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010857 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010858
10859 // First finger down on both spy and window
10860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010861 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010862 {10, 10}))
10863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10864 window->consumeMotionDown();
10865 spy->consumeMotionDown();
10866
10867 // Second finger down on the spy and window
10868 const MotionEvent secondFingerDownEvent =
10869 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10870 .displayId(ADISPLAY_ID_DEFAULT)
10871 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010872 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10873 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010874 .build();
10875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010876 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010877 InputEventInjectionSync::WAIT_FOR_RESULT))
10878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10879 spy->consumeMotionPointerDown(1);
10880 window->consumeMotionPointerDown(1);
10881
10882 // Spy window pilfers the pointers.
10883 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10884 window->consumeMotionCancel();
10885
10886 spy->assertNoEvents();
10887 window->assertNoEvents();
10888}
10889
10890/**
10891 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10892 * be sent to other windows
10893 */
10894TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10895 auto spy = createSpy();
10896 spy->setFrame(Rect(0, 0, 100, 100));
10897 auto window = createForeground();
10898 window->setFrame(Rect(0, 0, 200, 200));
10899
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010900 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010901
10902 // First finger down on both window and spy
10903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010904 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010905 {10, 10}))
10906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10907 window->consumeMotionDown();
10908 spy->consumeMotionDown();
10909
10910 // Spy window pilfers the pointers.
10911 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10912 window->consumeMotionCancel();
10913
10914 // Second finger down on the window only
10915 const MotionEvent secondFingerDownEvent =
10916 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10917 .displayId(ADISPLAY_ID_DEFAULT)
10918 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010919 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10920 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010921 .build();
10922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010923 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010924 InputEventInjectionSync::WAIT_FOR_RESULT))
10925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10926 window->consumeMotionDown();
10927 window->assertNoEvents();
10928
10929 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10930 spy->consumeMotionMove();
10931 spy->assertNoEvents();
10932}
10933
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010934/**
10935 * A window on the left and a window on the right. Also, a spy window that's above all of the
10936 * windows, and spanning both left and right windows.
10937 * Send simultaneous motion streams from two different devices, one to the left window, and another
10938 * to the right window.
10939 * Pilfer from spy window.
10940 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10941 */
10942TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10943 sp<FakeWindowHandle> spy = createSpy();
10944 spy->setFrame(Rect(0, 0, 200, 200));
10945 sp<FakeWindowHandle> leftWindow = createForeground();
10946 leftWindow->setFrame(Rect(0, 0, 100, 100));
10947
10948 sp<FakeWindowHandle> rightWindow = createForeground();
10949 rightWindow->setFrame(Rect(100, 0, 200, 100));
10950
10951 constexpr int32_t stylusDeviceId = 1;
10952 constexpr int32_t touchDeviceId = 2;
10953
10954 mDispatcher->onWindowInfosChanged(
10955 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10956
10957 // Stylus down on left window and spy
10958 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10959 .deviceId(stylusDeviceId)
10960 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10961 .build());
10962 leftWindow->consumeMotionEvent(
10963 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10964 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10965
10966 // Finger down on right window and spy - but spy already has stylus
10967 mDispatcher->notifyMotion(
10968 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10969 .deviceId(touchDeviceId)
10970 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10971 .build());
10972 rightWindow->consumeMotionEvent(
10973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010974 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010975
10976 // Act: pilfer from spy. Spy is currently receiving touch events.
10977 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010978 leftWindow->consumeMotionEvent(
10979 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010980 rightWindow->consumeMotionEvent(
10981 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10982
10983 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10984 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10985 .deviceId(stylusDeviceId)
10986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10987 .build());
10988 mDispatcher->notifyMotion(
10989 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10990 .deviceId(touchDeviceId)
10991 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10992 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010993 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010994
10995 spy->assertNoEvents();
10996 leftWindow->assertNoEvents();
10997 rightWindow->assertNoEvents();
10998}
10999
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011000TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11001 auto window = createForeground();
11002 auto spy = createSpy();
11003 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11004
11005 mDispatcher->notifyMotion(
11006 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11007 .deviceId(1)
11008 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11009 .build());
11010 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11011 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11012
11013 // Pilfer pointers from the spy window should fail.
11014 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11015 spy->assertNoEvents();
11016 window->assertNoEvents();
11017}
11018
Prabir Pradhand65552b2021-10-07 11:23:50 -070011019class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11020public:
11021 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11022 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11023 std::make_shared<FakeApplicationHandle>();
11024 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011025 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11026 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011027 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011028 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011029 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011030 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011031 overlay->setTrustedOverlay(true);
11032
11033 std::shared_ptr<FakeApplicationHandle> application =
11034 std::make_shared<FakeApplicationHandle>();
11035 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011036 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11037 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011038 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011039 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011040
11041 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011042 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011043 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011044 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011045 return {std::move(overlay), std::move(window)};
11046 }
11047
11048 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011049 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011050 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011051 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011052 }
11053
11054 void sendStylusEvent(int32_t action) {
11055 NotifyMotionArgs motionArgs =
11056 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11057 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011058 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011059 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011060 }
11061};
11062
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011063using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11064
11065TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011066 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011067 ScopedSilentDeath _silentDeath;
11068
Prabir Pradhand65552b2021-10-07 11:23:50 -070011069 auto [overlay, window] = setupStylusOverlayScenario();
11070 overlay->setTrustedOverlay(false);
11071 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011072 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11073 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011074 ".* not a trusted overlay");
11075}
11076
11077TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11078 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011079 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011080
11081 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11082 overlay->consumeMotionDown();
11083 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11084 overlay->consumeMotionUp();
11085
11086 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11087 window->consumeMotionDown();
11088 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11089 window->consumeMotionUp();
11090
11091 overlay->assertNoEvents();
11092 window->assertNoEvents();
11093}
11094
11095TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11096 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011097 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011098 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011099
11100 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11101 overlay->consumeMotionDown();
11102 window->consumeMotionDown();
11103 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11104 overlay->consumeMotionUp();
11105 window->consumeMotionUp();
11106
11107 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11108 window->consumeMotionDown();
11109 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11110 window->consumeMotionUp();
11111
11112 overlay->assertNoEvents();
11113 window->assertNoEvents();
11114}
11115
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011116/**
11117 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11118 * The scenario is as follows:
11119 * - The stylus interceptor overlay is configured as a spy window.
11120 * - The stylus interceptor spy receives the start of a new stylus gesture.
11121 * - It pilfers pointers and then configures itself to no longer be a spy.
11122 * - The stylus interceptor continues to receive the rest of the gesture.
11123 */
11124TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11125 auto [overlay, window] = setupStylusOverlayScenario();
11126 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011127 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011128
11129 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11130 overlay->consumeMotionDown();
11131 window->consumeMotionDown();
11132
11133 // The interceptor pilfers the pointers.
11134 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11135 window->consumeMotionCancel();
11136
11137 // The interceptor configures itself so that it is no longer a spy.
11138 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011139 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011140
11141 // It continues to receive the rest of the stylus gesture.
11142 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11143 overlay->consumeMotionMove();
11144 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11145 overlay->consumeMotionUp();
11146
11147 window->assertNoEvents();
11148}
11149
Prabir Pradhan5735a322022-04-11 17:23:34 +000011150struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011151 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011152 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011153 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11154 std::unique_ptr<InputDispatcher>& mDispatcher;
11155
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011156 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011157 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11158
11159 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011160 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011161 ADISPLAY_ID_DEFAULT, {100, 200},
11162 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11163 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11164 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11165 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11166 }
11167
11168 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011169 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011170 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011171 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011172 mPolicyFlags);
11173 }
11174
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011175 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011176 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11177 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011178 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11179 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011180 window->setOwnerInfo(mPid, mUid);
11181 return window;
11182 }
11183};
11184
11185using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11186
11187TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011188 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011189 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011190 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011191
11192 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11193 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11194 window->consumeMotionDown();
11195
11196 setFocusedWindow(window);
11197 window->consumeFocusEvent(true);
11198
11199 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11200 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11201 window->consumeKeyDown(ADISPLAY_ID_NONE);
11202}
11203
11204TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011205 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011206 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011207 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011208
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011209 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011210 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11211 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11212
11213 setFocusedWindow(window);
11214 window->consumeFocusEvent(true);
11215
11216 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11217 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11218 window->assertNoEvents();
11219}
11220
11221TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011222 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011223 auto window = owner.createWindow("Owned window");
11224 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011225 spy->setSpy(true);
11226 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011227 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011228
11229 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11230 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11231 spy->consumeMotionDown();
11232 window->consumeMotionDown();
11233}
11234
11235TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011236 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011237 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011238
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011239 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011240 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011241 randosSpy->setSpy(true);
11242 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011243 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011244
11245 // The event is targeted at owner's window, so injection should succeed, but the spy should
11246 // not receive the event.
11247 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11248 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11249 randosSpy->assertNoEvents();
11250 window->consumeMotionDown();
11251}
11252
11253TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011254 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011255 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011256
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011257 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011258 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011259 randosSpy->setSpy(true);
11260 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011261 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011262
11263 // A user that has injection permission can inject into any window.
11264 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011265 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011266 ADISPLAY_ID_DEFAULT));
11267 randosSpy->consumeMotionDown();
11268 window->consumeMotionDown();
11269
11270 setFocusedWindow(randosSpy);
11271 randosSpy->consumeFocusEvent(true);
11272
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011273 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011274 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11275 window->assertNoEvents();
11276}
11277
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011278TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011279 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011280 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011281
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011282 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011283 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011284 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11285 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011286 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011287
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011288 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011289 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11290 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11291 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011292 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011293}
11294
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011295using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11296
11297TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11299
11300 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11301 ADISPLAY_ID_DEFAULT);
11302 left->setFrame(Rect(0, 0, 100, 100));
11303 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11304 "Right Window", ADISPLAY_ID_DEFAULT);
11305 right->setFrame(Rect(100, 0, 200, 100));
11306 sp<FakeWindowHandle> spy =
11307 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11308 spy->setFrame(Rect(0, 0, 200, 100));
11309 spy->setTrustedOverlay(true);
11310 spy->setSpy(true);
11311
11312 mDispatcher->onWindowInfosChanged(
11313 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11314
11315 // Hover into the left window.
11316 mDispatcher->notifyMotion(
11317 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11318 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11319 .build());
11320
11321 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11322 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11323
11324 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11325 /*pointerId=*/0));
11326 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11327 /*pointerId=*/0));
11328 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11329 /*pointerId=*/0));
11330
11331 // Hover move to the right window.
11332 mDispatcher->notifyMotion(
11333 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11334 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11335 .build());
11336
11337 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11338 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11339 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11340
11341 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11342 /*pointerId=*/0));
11343 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11344 /*pointerId=*/0));
11345 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11346 /*pointerId=*/0));
11347
11348 // Stop hovering.
11349 mDispatcher->notifyMotion(
11350 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11351 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11352 .build());
11353
11354 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11355 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11356
11357 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11358 /*pointerId=*/0));
11359 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11360 /*pointerId=*/0));
11361 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11362 /*pointerId=*/0));
11363}
11364
11365TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11367
11368 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11369 ADISPLAY_ID_DEFAULT);
11370 left->setFrame(Rect(0, 0, 100, 100));
11371 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11372 "Right Window", ADISPLAY_ID_DEFAULT);
11373 right->setFrame(Rect(100, 0, 200, 100));
11374 sp<FakeWindowHandle> spy =
11375 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11376 spy->setFrame(Rect(0, 0, 200, 100));
11377 spy->setTrustedOverlay(true);
11378 spy->setSpy(true);
11379
11380 mDispatcher->onWindowInfosChanged(
11381 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11382
11383 // First pointer down on left window.
11384 mDispatcher->notifyMotion(
11385 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11386 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11387 .build());
11388
11389 left->consumeMotionDown();
11390 spy->consumeMotionDown();
11391
11392 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11393 /*pointerId=*/0));
11394 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11395 /*pointerId=*/0));
11396 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11397 /*pointerId=*/0));
11398
11399 // Second pointer down on right window.
11400 mDispatcher->notifyMotion(
11401 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11402 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11403 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11404 .build());
11405
11406 left->consumeMotionMove();
11407 right->consumeMotionDown();
11408 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11409
11410 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11411 /*pointerId=*/0));
11412 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11413 /*pointerId=*/0));
11414 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11415 /*pointerId=*/0));
11416 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11417 /*pointerId=*/1));
11418 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11419 /*pointerId=*/1));
11420 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11421 /*pointerId=*/1));
11422
11423 // Second pointer up.
11424 mDispatcher->notifyMotion(
11425 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11426 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11427 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11428 .build());
11429
11430 left->consumeMotionMove();
11431 right->consumeMotionUp();
11432 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11433
11434 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11435 /*pointerId=*/0));
11436 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11437 /*pointerId=*/0));
11438 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11439 /*pointerId=*/0));
11440 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11441 /*pointerId=*/1));
11442 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11443 /*pointerId=*/1));
11444 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11445 /*pointerId=*/1));
11446
11447 // First pointer up.
11448 mDispatcher->notifyMotion(
11449 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11450 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11451 .build());
11452
11453 left->consumeMotionUp();
11454 spy->consumeMotionUp();
11455
11456 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11457 /*pointerId=*/0));
11458 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11459 /*pointerId=*/0));
11460 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11461 /*pointerId=*/0));
11462}
11463
11464TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11466
11467 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11468 ADISPLAY_ID_DEFAULT);
11469 left->setFrame(Rect(0, 0, 100, 100));
11470 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11471 "Right Window", ADISPLAY_ID_DEFAULT);
11472 right->setFrame(Rect(100, 0, 200, 100));
11473
11474 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11475
11476 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11477 /*pointerId=*/0));
11478 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11479 /*pointerId=*/0));
11480
11481 // Hover move into the window.
11482 mDispatcher->notifyMotion(
11483 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11484 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11485 .rawXCursorPosition(50)
11486 .rawYCursorPosition(50)
11487 .deviceId(DEVICE_ID)
11488 .build());
11489
11490 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11491
11492 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11493 /*pointerId=*/0));
11494
11495 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11496 mDispatcher->notifyMotion(
11497 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11498 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11499 .rawXCursorPosition(51)
11500 .rawYCursorPosition(50)
11501 .deviceId(SECOND_DEVICE_ID)
11502 .build());
11503
11504 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11505 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11506
11507 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11508 // a HOVER_EXIT from the first device.
11509 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11510 /*pointerId=*/0));
11511 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11512 SECOND_DEVICE_ID,
11513 /*pointerId=*/0));
11514
11515 // Move the mouse outside the window. Document the current behavior, where the window does not
11516 // receive HOVER_EXIT even though the mouse left the window.
11517 mDispatcher->notifyMotion(
11518 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11519 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11520 .rawXCursorPosition(150)
11521 .rawYCursorPosition(50)
11522 .deviceId(SECOND_DEVICE_ID)
11523 .build());
11524
11525 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11526 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11527 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11528 /*pointerId=*/0));
11529 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11530 SECOND_DEVICE_ID,
11531 /*pointerId=*/0));
11532}
11533
Garfield Tane84e6f92019-08-29 17:28:41 -070011534} // namespace android::inputdispatcher