blob: e230a91a3168ef876895b008b32ed211c9126a42 [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/**
3416 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3417 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3418 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3419 * While the mouse is down, new move events from the touch device should be ignored.
3420 */
3421TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3422 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3423 sp<FakeWindowHandle> spyWindow =
3424 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3425 spyWindow->setFrame(Rect(0, 0, 200, 200));
3426 spyWindow->setTrustedOverlay(true);
3427 spyWindow->setSpy(true);
3428 sp<FakeWindowHandle> window =
3429 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3430 window->setFrame(Rect(0, 0, 200, 200));
3431
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003432 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003433
3434 const int32_t mouseDeviceId = 7;
3435 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003436
3437 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3439 .deviceId(mouseDeviceId)
3440 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3441 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003442 spyWindow->consumeMotionEvent(
3443 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3444 window->consumeMotionEvent(
3445 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3446
3447 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003448 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3449 .deviceId(touchDeviceId)
3450 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3451 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003452 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3453 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3454 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3455 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3456
Prabir Pradhan678438e2023-04-13 19:32:51 +00003457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3458 .deviceId(touchDeviceId)
3459 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3460 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003461 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3462 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3463
3464 // Pilfer the stream
3465 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3466 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3467
Prabir Pradhan678438e2023-04-13 19:32:51 +00003468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3469 .deviceId(touchDeviceId)
3470 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3471 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003472 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3473
3474 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3476 .deviceId(mouseDeviceId)
3477 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3479 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003480
3481 spyWindow->consumeMotionEvent(
3482 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3483 spyWindow->consumeMotionEvent(
3484 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3486
Prabir Pradhan678438e2023-04-13 19:32:51 +00003487 mDispatcher->notifyMotion(
3488 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3489 .deviceId(mouseDeviceId)
3490 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3491 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003494 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3495 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3496
3497 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3499 .deviceId(mouseDeviceId)
3500 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3501 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3502 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003503 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3504 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3505
3506 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3508 .deviceId(touchDeviceId)
3509 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3510 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003511
3512 // No more events
3513 spyWindow->assertNoEvents();
3514 window->assertNoEvents();
3515}
3516
3517/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003518 * On the display, have a single window, and also an area where there's no window.
3519 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3520 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3521 */
3522TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3524 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003525 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003526
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003528
3529 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003530 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003531
3532 mDispatcher->waitForIdle();
3533 window->assertNoEvents();
3534
3535 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003537 mDispatcher->waitForIdle();
3538 window->consumeMotionDown();
3539}
3540
3541/**
3542 * Same test as above, but instead of touching the empty space, the first touch goes to
3543 * non-touchable window.
3544 */
3545TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3547 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003548 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003549 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3550 window1->setTouchable(false);
3551 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003552 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003553 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3554
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003555 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003556
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003557 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003558 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003559
3560 mDispatcher->waitForIdle();
3561 window1->assertNoEvents();
3562 window2->assertNoEvents();
3563
3564 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003565 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003566 mDispatcher->waitForIdle();
3567 window2->consumeMotionDown();
3568}
3569
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003570/**
3571 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3572 * to the event time of the first ACTION_DOWN sent to the particular window.
3573 */
3574TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3576 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003577 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003578 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3579 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003580 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003581 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3582
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003583 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003584
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003585 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003586 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003587
3588 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003589
3590 MotionEvent* motionEvent1 = window1->consumeMotion();
3591 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003592 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003593 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3594 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003595
3596 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003597 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003598 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003599 MotionEvent* motionEvent2 = window2->consumeMotion();
3600 ASSERT_NE(motionEvent2, nullptr);
3601 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003603 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003604
3605 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003606 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003607 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003608 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003609
3610 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003611 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003612 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003613 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003614
3615 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3616 window1->consumeMotionMove();
3617 window1->assertNoEvents();
3618
3619 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003620 mDispatcher->notifyMotion(
3621 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003623 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003624
Prabir Pradhan678438e2023-04-13 19:32:51 +00003625 mDispatcher->notifyMotion(
3626 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003627 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003628 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003629}
3630
Garfield Tandf26e862020-07-01 20:18:19 -07003631TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003632 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003633 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003634 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003635 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003636 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003637 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003638 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003639
3640 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3641
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003642 mDispatcher->onWindowInfosChanged(
3643 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003644
3645 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003647 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003648 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3649 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003650 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003651 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003652 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003653
3654 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003656 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003657 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3658 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003659 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003660 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003661 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3662 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003663
3664 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003666 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003667 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3668 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003669 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003670 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003671 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3672 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003673
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003675 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003676 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3677 AINPUT_SOURCE_MOUSE)
3678 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3679 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003680 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003681 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003682 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003683
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_BUTTON_RELEASE,
3687 AINPUT_SOURCE_MOUSE)
3688 .buttonState(0)
3689 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003690 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003691 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003692 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003693
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003695 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003696 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3697 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003698 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003699 .build()));
3700 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3701
3702 // Move mouse cursor back to right window
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_HOVER_MOVE,
3706 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003707 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003708 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003709 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003710
3711 // No more events
3712 windowLeft->assertNoEvents();
3713 windowRight->assertNoEvents();
3714}
3715
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003716/**
3717 * Put two fingers down (and don't release them) and click the mouse button.
3718 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3719 * currently active gesture should be canceled, and the new one should proceed.
3720 */
3721TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3723 sp<FakeWindowHandle> window =
3724 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3725 window->setFrame(Rect(0, 0, 600, 800));
3726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003728
3729 const int32_t touchDeviceId = 4;
3730 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003731
3732 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3734 .deviceId(touchDeviceId)
3735 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3736 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003737
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3739 .deviceId(touchDeviceId)
3740 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3741 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3742 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003743 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3744 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3745
3746 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3748 .deviceId(mouseDeviceId)
3749 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3750 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3751 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003752 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3753 WithPointerCount(2u)));
3754 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3755
Prabir Pradhan678438e2023-04-13 19:32:51 +00003756 mDispatcher->notifyMotion(
3757 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3758 .deviceId(mouseDeviceId)
3759 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3760 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3761 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3762 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003763 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3764
3765 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3766 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3768 .deviceId(touchDeviceId)
3769 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3770 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3771 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003772 window->assertNoEvents();
3773}
3774
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003775TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3777
3778 sp<FakeWindowHandle> spyWindow =
3779 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3780 spyWindow->setFrame(Rect(0, 0, 600, 800));
3781 spyWindow->setTrustedOverlay(true);
3782 spyWindow->setSpy(true);
3783 sp<FakeWindowHandle> window =
3784 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3785 window->setFrame(Rect(0, 0, 600, 800));
3786
3787 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003788 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003789
3790 // Send mouse cursor to the window
3791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003792 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003793 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3794 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003795 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003796 .build()));
3797
3798 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3799 WithSource(AINPUT_SOURCE_MOUSE)));
3800 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3801 WithSource(AINPUT_SOURCE_MOUSE)));
3802
3803 window->assertNoEvents();
3804 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003805}
3806
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003807TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3809
3810 sp<FakeWindowHandle> spyWindow =
3811 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3812 spyWindow->setFrame(Rect(0, 0, 600, 800));
3813 spyWindow->setTrustedOverlay(true);
3814 spyWindow->setSpy(true);
3815 sp<FakeWindowHandle> window =
3816 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3817 window->setFrame(Rect(0, 0, 600, 800));
3818
3819 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003820 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003821
3822 // Send mouse cursor to the window
3823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003824 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003825 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3826 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003828 .build()));
3829
3830 // Move mouse cursor
3831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003832 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003833 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3834 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003835 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003836 .build()));
3837
3838 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3839 WithSource(AINPUT_SOURCE_MOUSE)));
3840 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3841 WithSource(AINPUT_SOURCE_MOUSE)));
3842 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3843 WithSource(AINPUT_SOURCE_MOUSE)));
3844 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3845 WithSource(AINPUT_SOURCE_MOUSE)));
3846 // Touch down on the window
3847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003848 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003849 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3850 AINPUT_SOURCE_TOUCHSCREEN)
3851 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003852 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003853 .build()));
3854 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3855 WithSource(AINPUT_SOURCE_MOUSE)));
3856 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3857 WithSource(AINPUT_SOURCE_MOUSE)));
3858 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3859 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3860 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3861 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3862
3863 // pilfer the motion, retaining the gesture on the spy window.
3864 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3865 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3866 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3867
3868 // Touch UP on the window
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_UP,
3872 AINPUT_SOURCE_TOUCHSCREEN)
3873 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003874 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003875 .build()));
3876 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3877 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3878
3879 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3880 // to send a new gesture. It should again go to both windows (spy and the window below), just
3881 // like the first gesture did, before pilfering. The window configuration has not changed.
3882
3883 // One more tap - DOWN
3884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003885 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003886 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3887 AINPUT_SOURCE_TOUCHSCREEN)
3888 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003889 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003890 .build()));
3891 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3892 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3893 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3894 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3895
3896 // Touch UP on the window
3897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003898 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003899 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3900 AINPUT_SOURCE_TOUCHSCREEN)
3901 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003902 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003903 .build()));
3904 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3905 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3906 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3907 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3908
3909 window->assertNoEvents();
3910 spyWindow->assertNoEvents();
3911}
3912
Garfield Tandf26e862020-07-01 20:18:19 -07003913// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3914// directly in this test.
3915TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003917 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003918 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003919 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003920
3921 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3922
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003923 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003924
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003926 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003927 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3928 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003929 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003930 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003931 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003932 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003934 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003935 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3936 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003937 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003938 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003939 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3940 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003941
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003943 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003944 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3945 AINPUT_SOURCE_MOUSE)
3946 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3947 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003949 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003950 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003951
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003953 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003954 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3955 AINPUT_SOURCE_MOUSE)
3956 .buttonState(0)
3957 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003958 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003959 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003960 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003961
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003963 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003964 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3965 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003967 .build()));
3968 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3969
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003970 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3971 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3972 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003973 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003974 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3975 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003976 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003977 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003978 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003979}
3980
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003981/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003982 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3983 * is generated.
3984 */
3985TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3987 sp<FakeWindowHandle> window =
3988 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3989 window->setFrame(Rect(0, 0, 1200, 800));
3990
3991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3992
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003993 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003994
3995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003996 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3998 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004000 .build()));
4001 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4002
4003 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004004 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004005 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4006}
4007
4008/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004009 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4010 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004011TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4012 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4013 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004014 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4015 sp<FakeWindowHandle> window =
4016 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4017 window->setFrame(Rect(0, 0, 1200, 800));
4018
4019 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4020
4021 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4022
4023 MotionEventBuilder hoverEnterBuilder =
4024 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4026 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4028 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4030 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4031 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4032 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4033}
4034
4035/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004036 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4037 */
4038TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4039 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4040 sp<FakeWindowHandle> window =
4041 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4042 window->setFrame(Rect(0, 0, 100, 100));
4043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004044 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004045
4046 const int32_t mouseDeviceId = 7;
4047 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004048
4049 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4051 .deviceId(mouseDeviceId)
4052 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4053 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004054 window->consumeMotionEvent(
4055 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4056
4057 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4059 .deviceId(touchDeviceId)
4060 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4061 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004062
4063 window->consumeMotionEvent(
4064 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4065 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4066}
4067
4068/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004069 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004070 * The tap causes a HOVER_EXIT event to be generated because the current event
4071 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004072 */
4073TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4075 sp<FakeWindowHandle> window =
4076 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4077 window->setFrame(Rect(0, 0, 100, 100));
4078
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004079 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4081 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4082 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004083 ASSERT_NO_FATAL_FAILURE(
4084 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4085 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004086
4087 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4089 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4090 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004091 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004092 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4093 WithSource(AINPUT_SOURCE_MOUSE))));
4094
4095 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004096 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4097 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4098
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4100 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4101 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004102 ASSERT_NO_FATAL_FAILURE(
4103 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4104 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4105}
4106
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004107TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4109 sp<FakeWindowHandle> windowDefaultDisplay =
4110 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4111 ADISPLAY_ID_DEFAULT);
4112 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4113 sp<FakeWindowHandle> windowSecondDisplay =
4114 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4115 SECOND_DISPLAY_ID);
4116 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4117
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004118 mDispatcher->onWindowInfosChanged(
4119 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004120
4121 // Set cursor position in window in default display and check that hover enter and move
4122 // events are generated.
4123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004124 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004125 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4126 AINPUT_SOURCE_MOUSE)
4127 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004128 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004129 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004130 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004131
4132 // Remove all windows in secondary display and check that no event happens on window in
4133 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004134 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4135
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004136 windowDefaultDisplay->assertNoEvents();
4137
4138 // Move cursor position in window in default display and check that only hover move
4139 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004140 mDispatcher->onWindowInfosChanged(
4141 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004144 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4145 AINPUT_SOURCE_MOUSE)
4146 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004147 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004148 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004149 windowDefaultDisplay->consumeMotionEvent(
4150 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4151 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004152 windowDefaultDisplay->assertNoEvents();
4153}
4154
Garfield Tan00f511d2019-06-12 16:55:40 -07004155TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004157
4158 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004159 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004160 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004161 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004162 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004163 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004164
4165 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4166
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004167 mDispatcher->onWindowInfosChanged(
4168 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004169
4170 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4171 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004173 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004174 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004175 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004176 windowRight->assertNoEvents();
4177}
4178
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004179TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004181 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4182 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004183 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004184
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004185 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004186 setFocusedWindow(window);
4187
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004188 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004189
Prabir Pradhan678438e2023-04-13 19:32:51 +00004190 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004191
4192 // Window should receive key down event.
4193 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4194
4195 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4196 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004197 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004198 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004199 AKEY_EVENT_FLAG_CANCELED);
4200}
4201
4202TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004204 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4205 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004206
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004207 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004208
Prabir Pradhan678438e2023-04-13 19:32:51 +00004209 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4210 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004211
4212 // Window should receive motion down event.
4213 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4214
4215 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4216 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004217 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004218 window->consumeMotionEvent(
4219 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004220}
4221
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004222TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4224 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4225 "Fake Window", ADISPLAY_ID_DEFAULT);
4226
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004227 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004228
4229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4230 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4231 .build());
4232
4233 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4234
4235 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4236 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4238
4239 // After the device has been reset, a new hovering stream can be sent to the window
4240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4241 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4242 .build());
4243 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4244}
4245
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004246TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4247 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004248 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4249 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004250 window->setFocusable(true);
4251
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004252 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004253 setFocusedWindow(window);
4254
4255 window->consumeFocusEvent(true);
4256
Prabir Pradhan678438e2023-04-13 19:32:51 +00004257 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004258 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4259 const nsecs_t injectTime = keyArgs.eventTime;
4260 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004261 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004262 // The dispatching time should be always greater than or equal to intercept key timeout.
4263 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4264 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4265 std::chrono::nanoseconds(interceptKeyTimeout).count());
4266}
4267
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004268/**
4269 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4270 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004271TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004273 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4274 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004275 window->setFocusable(true);
4276
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004277 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004278 setFocusedWindow(window);
4279
4280 window->consumeFocusEvent(true);
4281
Prabir Pradhan678438e2023-04-13 19:32:51 +00004282 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004283 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004284
4285 // Set a value that's significantly larger than the default consumption timeout. If the
4286 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4287 mFakePolicy->setInterceptKeyTimeout(600ms);
4288 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4289 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004290 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4291}
4292
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004293/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004294 * Two windows. First is a regular window. Second does not overlap with the first, and has
4295 * WATCH_OUTSIDE_TOUCH.
4296 * Both windows are owned by the same UID.
4297 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4298 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4299 */
4300TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004302 sp<FakeWindowHandle> window =
4303 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004304 window->setFrame(Rect{0, 0, 100, 100});
4305
4306 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004307 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004308 ADISPLAY_ID_DEFAULT);
4309 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4310 outsideWindow->setWatchOutsideTouch(true);
4311 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004312 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004313
4314 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004315 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4316 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4317 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004318 window->consumeMotionDown();
4319 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4320 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4321 outsideWindow->consumeMotionEvent(
4322 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004323
4324 // Ensure outsideWindow doesn't get any more events for the gesture.
4325 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4326 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4327 window->consumeMotionMove();
4328 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004329}
4330
4331/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004332 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4333 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4334 * ACTION_OUTSIDE event is sent per gesture.
4335 */
4336TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4337 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004339 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4340 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004341 window->setWatchOutsideTouch(true);
4342 window->setFrame(Rect{0, 0, 100, 100});
4343 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004344 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4345 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004346 secondWindow->setFrame(Rect{100, 100, 200, 200});
4347 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004348 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4349 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004350 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004351 mDispatcher->onWindowInfosChanged(
4352 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004353
4354 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004355 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4356 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4357 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004358 window->assertNoEvents();
4359 secondWindow->assertNoEvents();
4360
4361 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4362 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004363 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4364 ADISPLAY_ID_DEFAULT,
4365 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004366 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4367 window->consumeMotionEvent(
4368 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004369 secondWindow->consumeMotionDown();
4370 thirdWindow->assertNoEvents();
4371
4372 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4373 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004374 mDispatcher->notifyMotion(
4375 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4376 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004377 window->assertNoEvents();
4378 secondWindow->consumeMotionMove();
4379 thirdWindow->consumeMotionDown();
4380}
4381
Prabir Pradhan814fe082022-07-22 20:22:18 +00004382TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004384 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4385 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004386 window->setFocusable(true);
4387
Patrick Williamsd828f302023-04-28 17:52:08 -05004388 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004389 setFocusedWindow(window);
4390
4391 window->consumeFocusEvent(true);
4392
Prabir Pradhan678438e2023-04-13 19:32:51 +00004393 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4394 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4395 mDispatcher->notifyKey(keyDown);
4396 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004397
4398 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4399 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4400
4401 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004402 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004403
4404 window->consumeFocusEvent(false);
4405
Prabir Pradhan678438e2023-04-13 19:32:51 +00004406 mDispatcher->notifyKey(keyDown);
4407 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004408 window->assertNoEvents();
4409}
4410
Arthur Hung96483742022-11-15 03:30:48 +00004411TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4413 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4414 "Fake Window", ADISPLAY_ID_DEFAULT);
4415 // Ensure window is non-split and have some transform.
4416 window->setPreventSplitting(true);
4417 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004419
4420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004421 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004422 {50, 50}))
4423 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4424 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4425
4426 const MotionEvent secondFingerDownEvent =
4427 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4428 .displayId(ADISPLAY_ID_DEFAULT)
4429 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004430 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4431 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004432 .build();
4433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004434 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004435 InputEventInjectionSync::WAIT_FOR_RESULT))
4436 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4437
4438 const MotionEvent* event = window->consumeMotion();
4439 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4440 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4441 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4442 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4443 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4444}
4445
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004446/**
4447 * Two windows: a splittable and a non-splittable.
4448 * The non-splittable window shouldn't receive any "incomplete" gestures.
4449 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4450 * The second pointer should be dropped because the initial window is splittable, so it won't get
4451 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4452 * "incomplete" gestures.
4453 */
4454TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4456 sp<FakeWindowHandle> leftWindow =
4457 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4458 ADISPLAY_ID_DEFAULT);
4459 leftWindow->setPreventSplitting(false);
4460 leftWindow->setFrame(Rect(0, 0, 100, 100));
4461 sp<FakeWindowHandle> rightWindow =
4462 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4463 ADISPLAY_ID_DEFAULT);
4464 rightWindow->setPreventSplitting(true);
4465 rightWindow->setFrame(Rect(100, 100, 200, 200));
4466 mDispatcher->onWindowInfosChanged(
4467 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4468
4469 // Touch down on left, splittable window
4470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4471 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4472 .build());
4473 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4474
4475 mDispatcher->notifyMotion(
4476 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4477 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4478 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4479 .build());
4480 leftWindow->assertNoEvents();
4481 rightWindow->assertNoEvents();
4482}
4483
Harry Cuttsb166c002023-05-09 13:06:05 +00004484TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4486 sp<FakeWindowHandle> window =
4487 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4488 window->setFrame(Rect(0, 0, 400, 400));
4489 sp<FakeWindowHandle> trustedOverlay =
4490 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4491 ADISPLAY_ID_DEFAULT);
4492 trustedOverlay->setSpy(true);
4493 trustedOverlay->setTrustedOverlay(true);
4494
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004495 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004496
4497 // Start a three-finger touchpad swipe
4498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4499 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4500 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4501 .build());
4502 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4503 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4504 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4505 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4506 .build());
4507 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4508 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4509 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4510 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4511 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4512 .build());
4513
4514 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4515 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4516 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4517
4518 // Move the swipe a bit
4519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4520 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4521 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4522 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4523 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4524 .build());
4525
4526 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4527
4528 // End the swipe
4529 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4530 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4531 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4532 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4533 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4534 .build());
4535 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4536 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4537 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4538 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4539 .build());
4540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4541 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4542 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4543 .build());
4544
4545 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4546 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4547 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4548
4549 window->assertNoEvents();
4550}
4551
4552TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4554 sp<FakeWindowHandle> window =
4555 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4556 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004557 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004558
4559 // Start a three-finger touchpad swipe
4560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4561 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4562 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4563 .build());
4564 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4565 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4566 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4567 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4568 .build());
4569 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4570 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4571 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4572 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4573 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4574 .build());
4575
4576 // Move the swipe a bit
4577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4578 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4579 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4580 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4581 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4582 .build());
4583
4584 // End the swipe
4585 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4586 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4587 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4588 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4589 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4590 .build());
4591 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4592 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4593 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4594 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4595 .build());
4596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4597 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4598 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4599 .build());
4600
4601 window->assertNoEvents();
4602}
4603
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004604/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004605 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4606 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004607 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004608 */
4609TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4610 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4611 sp<FakeWindowHandle> window =
4612 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4613 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004614 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004615
4616 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4618 .downTime(baseTime + 10)
4619 .eventTime(baseTime + 10)
4620 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4621 .build());
4622
4623 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4624
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004625 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004626 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004627
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004628 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004629
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004630 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4631 .downTime(baseTime + 10)
4632 .eventTime(baseTime + 30)
4633 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4634 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4635 .build());
4636
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004637 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4638
4639 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004640 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4641 .downTime(baseTime + 10)
4642 .eventTime(baseTime + 40)
4643 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4644 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4645 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004646
4647 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4648
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4650 .downTime(baseTime + 10)
4651 .eventTime(baseTime + 50)
4652 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4653 .build());
4654
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004655 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4656
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4658 .downTime(baseTime + 60)
4659 .eventTime(baseTime + 60)
4660 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4661 .build());
4662
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004663 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004664}
4665
4666/**
Hu Guo771a7692023-09-17 20:51:08 +08004667 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4668 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4669 * its coordinates should be converted by the transform of the windows of target screen.
4670 */
4671TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4672 // This case will create a window and a spy window on the default display and mirror
4673 // window on the second display. cancel event is sent through spy window pilferPointers
4674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4675
4676 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4677 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4678 spyWindowDefaultDisplay->setTrustedOverlay(true);
4679 spyWindowDefaultDisplay->setSpy(true);
4680
4681 sp<FakeWindowHandle> windowDefaultDisplay =
4682 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4683 ADISPLAY_ID_DEFAULT);
4684 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4685
4686 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4687 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4688
4689 // Add the windows to the dispatcher
4690 mDispatcher->onWindowInfosChanged(
4691 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4692 *windowSecondDisplay->getInfo()},
4693 {},
4694 0,
4695 0});
4696
4697 // Send down to ADISPLAY_ID_DEFAULT
4698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4699 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4700 {100, 100}))
4701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4702
4703 spyWindowDefaultDisplay->consumeMotionDown();
4704 windowDefaultDisplay->consumeMotionDown();
4705
4706 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4707
4708 // windowDefaultDisplay gets cancel
4709 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4710 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4711
4712 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4713 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4714 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4715 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4716 EXPECT_EQ(100, event->getX(0));
4717 EXPECT_EQ(100, event->getY(0));
4718}
4719
4720/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004721 * Ensure the correct coordinate spaces are used by InputDispatcher.
4722 *
4723 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4724 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4725 * space.
4726 */
4727class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4728public:
4729 void SetUp() override {
4730 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004731 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004732 }
4733
4734 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4735 gui::DisplayInfo info;
4736 info.displayId = displayId;
4737 info.transform = transform;
4738 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004739 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004740 }
4741
4742 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4743 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004744 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004745 }
4746
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004747 void removeAllWindowsAndDisplays() {
4748 mDisplayInfos.clear();
4749 mWindowInfos.clear();
4750 }
4751
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004752 // Set up a test scenario where the display has a scaled projection and there are two windows
4753 // on the display.
4754 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4755 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4756 // respectively.
4757 ui::Transform displayTransform;
4758 displayTransform.set(2, 0, 0, 4);
4759 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4760
4761 std::shared_ptr<FakeApplicationHandle> application =
4762 std::make_shared<FakeApplicationHandle>();
4763
4764 // Add two windows to the display. Their frames are represented in the display space.
4765 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004766 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4767 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004768 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4769 addWindow(firstWindow);
4770
4771 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004772 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4773 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004774 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4775 addWindow(secondWindow);
4776 return {std::move(firstWindow), std::move(secondWindow)};
4777 }
4778
4779private:
4780 std::vector<gui::DisplayInfo> mDisplayInfos;
4781 std::vector<gui::WindowInfo> mWindowInfos;
4782};
4783
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004784TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004785 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4786 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004787 // selected so that if the hit test was performed with the point and the bounds being in
4788 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004789 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4790 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4791 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004792
4793 firstWindow->consumeMotionDown();
4794 secondWindow->assertNoEvents();
4795}
4796
4797// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4798// the event should be treated as being in the logical display space.
4799TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4800 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4801 // Send down to the first window. The point is represented in the logical display space. The
4802 // point is selected so that if the hit test was done in logical display space, then it would
4803 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004804 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004805 PointF{75 * 2, 55 * 4});
4806
4807 firstWindow->consumeMotionDown();
4808 secondWindow->assertNoEvents();
4809}
4810
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004811// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4812// event should be treated as being in the logical display space.
4813TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4814 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4815
4816 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4817 ui::Transform injectedEventTransform;
4818 injectedEventTransform.set(matrix);
4819 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4820 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4821
4822 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4823 .displayId(ADISPLAY_ID_DEFAULT)
4824 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004825 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004826 .x(untransformedPoint.x)
4827 .y(untransformedPoint.y))
4828 .build();
4829 event.transform(matrix);
4830
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004831 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004832 InputEventInjectionSync::WAIT_FOR_RESULT);
4833
4834 firstWindow->consumeMotionDown();
4835 secondWindow->assertNoEvents();
4836}
4837
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004838TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4839 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4840
4841 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004842 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4843 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4844 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004845
4846 firstWindow->assertNoEvents();
4847 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004848 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004849 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4850
4851 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4852 EXPECT_EQ(300, event->getRawX(0));
4853 EXPECT_EQ(880, event->getRawY(0));
4854
4855 // Ensure that the x and y values are in the window's coordinate space.
4856 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4857 // the logical display space. This will be the origin of the window space.
4858 EXPECT_EQ(100, event->getX(0));
4859 EXPECT_EQ(80, event->getY(0));
4860}
4861
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004862TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4863 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4864 // The monitor will always receive events in the logical display's coordinate space, because
4865 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004866 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004867
4868 // Send down to the first window.
4869 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4870 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4871 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4872 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4873
4874 // Second pointer goes down on second window.
4875 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4876 ADISPLAY_ID_DEFAULT,
4877 {PointF{50, 100}, PointF{150, 220}}));
4878 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4879 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4880 {1, PointF{300, 880}}};
4881 monitor.consumeMotionEvent(
4882 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4883
4884 mDispatcher->cancelCurrentTouch();
4885
4886 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4887 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4888 monitor.consumeMotionEvent(
4889 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4890}
4891
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004892TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4893 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4894
4895 // Send down to the first window.
4896 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4897 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4898 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4899
4900 // The pointer is transferred to the second window, and the second window receives it in the
4901 // correct coordinate space.
4902 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4903 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4904 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4905}
4906
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004907TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4908 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4909
4910 // Send hover move to the second window, and ensure it shows up as hover enter.
4911 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4912 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4913 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4914 WithCoords(100, 80), WithRawCoords(300, 880)));
4915
4916 // Touch down at the same location and ensure a hover exit is synthesized.
4917 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4918 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4919 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4920 WithRawCoords(300, 880)));
4921 secondWindow->consumeMotionEvent(
4922 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4923 secondWindow->assertNoEvents();
4924 firstWindow->assertNoEvents();
4925}
4926
Prabir Pradhan453ae732023-10-13 14:30:14 +00004927// Same as above, but while the window is being mirrored.
4928TEST_F(InputDispatcherDisplayProjectionTest,
4929 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4930 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4931
4932 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4933 ui::Transform secondDisplayTransform;
4934 secondDisplayTransform.set(matrix);
4935 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4936
4937 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4938 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4939 addWindow(secondWindowClone);
4940
4941 // Send hover move to the second window, and ensure it shows up as hover enter.
4942 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4943 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4944 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4945 WithCoords(100, 80), WithRawCoords(300, 880)));
4946
4947 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4948 // display.
4949 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4950 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4951 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4952 WithRawCoords(300, 880)));
4953 secondWindow->consumeMotionEvent(
4954 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4955 secondWindow->assertNoEvents();
4956 firstWindow->assertNoEvents();
4957}
4958
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004959TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4960 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4961
4962 // Send hover enter to second window
4963 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4964 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4965 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4966 WithCoords(100, 80), WithRawCoords(300, 880)));
4967
4968 mDispatcher->cancelCurrentTouch();
4969
4970 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4971 WithRawCoords(300, 880)));
4972 secondWindow->assertNoEvents();
4973 firstWindow->assertNoEvents();
4974}
4975
Prabir Pradhan453ae732023-10-13 14:30:14 +00004976// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004977TEST_F(InputDispatcherDisplayProjectionTest,
4978 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4979 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4980
4981 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4982 ui::Transform secondDisplayTransform;
4983 secondDisplayTransform.set(matrix);
4984 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4985
4986 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4987 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4988 addWindow(secondWindowClone);
4989
4990 // Send hover enter to second window
4991 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4992 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4993 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4994 WithCoords(100, 80), WithRawCoords(300, 880),
4995 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4996
4997 mDispatcher->cancelCurrentTouch();
4998
4999 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5000 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5001 WithRawCoords(300, 880),
5002 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5003 secondWindow->assertNoEvents();
5004 firstWindow->assertNoEvents();
5005}
5006
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005007/** Ensure consistent behavior of InputDispatcher in all orientations. */
5008class InputDispatcherDisplayOrientationFixture
5009 : public InputDispatcherDisplayProjectionTest,
5010 public ::testing::WithParamInterface<ui::Rotation> {};
5011
5012// This test verifies the touchable region of a window for all rotations of the display by tapping
5013// in different locations on the display, specifically points close to the four corners of a
5014// window.
5015TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5016 constexpr static int32_t displayWidth = 400;
5017 constexpr static int32_t displayHeight = 800;
5018
5019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5020
5021 const auto rotation = GetParam();
5022
5023 // Set up the display with the specified rotation.
5024 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5025 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5026 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5027 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5028 logicalDisplayWidth, logicalDisplayHeight);
5029 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5030
5031 // Create a window with its bounds determined in the logical display.
5032 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5033 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5034 sp<FakeWindowHandle> window =
5035 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5036 window->setFrame(frameInDisplay, displayTransform);
5037 addWindow(window);
5038
5039 // The following points in logical display space should be inside the window.
5040 static const std::array<vec2, 4> insidePoints{
5041 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5042 for (const auto pointInsideWindow : insidePoints) {
5043 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5044 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005045 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5046 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5047 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005048 window->consumeMotionDown();
5049
Prabir Pradhan678438e2023-04-13 19:32:51 +00005050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5051 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5052 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005053 window->consumeMotionUp();
5054 }
5055
5056 // The following points in logical display space should be outside the window.
5057 static const std::array<vec2, 5> outsidePoints{
5058 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5059 for (const auto pointOutsideWindow : outsidePoints) {
5060 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5061 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005062 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5063 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5064 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005065
Prabir Pradhan678438e2023-04-13 19:32:51 +00005066 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5067 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5068 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005069 }
5070 window->assertNoEvents();
5071}
5072
5073// Run the precision tests for all rotations.
5074INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5075 InputDispatcherDisplayOrientationFixture,
5076 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5077 ui::ROTATION_270),
5078 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5079 return ftl::enum_string(testParamInfo.param);
5080 });
5081
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005082using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5083 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005084
5085class TransferTouchFixture : public InputDispatcherTest,
5086 public ::testing::WithParamInterface<TransferFunction> {};
5087
5088TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005090
5091 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005092 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005093 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5094 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005095 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005096 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005097 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5098 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005099 sp<FakeWindowHandle> wallpaper =
5100 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5101 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005102 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005103 mDispatcher->onWindowInfosChanged(
5104 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005105
5106 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005107 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5108 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005109
Svet Ganov5d3bc372020-01-26 23:11:07 -08005110 // Only the first window should get the down event
5111 firstWindow->consumeMotionDown();
5112 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005113 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005114
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005115 // Transfer touch to the second window
5116 TransferFunction f = GetParam();
5117 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5118 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005119 // The first window gets cancel and the second gets down
5120 firstWindow->consumeMotionCancel();
5121 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005122 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005123
5124 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005125 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5126 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005127 // The first window gets no events and the second gets up
5128 firstWindow->assertNoEvents();
5129 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005130 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005131}
5132
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005133/**
5134 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5135 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5136 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5137 * natural to the user.
5138 * In this test, we are sending a pointer to both spy window and first window. We then try to
5139 * transfer touch to the second window. The dispatcher should identify the first window as the
5140 * one that should lose the gesture, and therefore the action should be to move the gesture from
5141 * the first window to the second.
5142 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5143 * the other API, as well.
5144 */
5145TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5147
5148 // Create a couple of windows + a spy window
5149 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005150 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005151 spyWindow->setTrustedOverlay(true);
5152 spyWindow->setSpy(true);
5153 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005154 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005155 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005156 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005157
5158 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005159 mDispatcher->onWindowInfosChanged(
5160 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005161
5162 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005163 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5164 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005165 // Only the first window and spy should get the down event
5166 spyWindow->consumeMotionDown();
5167 firstWindow->consumeMotionDown();
5168
5169 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5170 // if f === 'transferTouch'.
5171 TransferFunction f = GetParam();
5172 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5173 ASSERT_TRUE(success);
5174 // The first window gets cancel and the second gets down
5175 firstWindow->consumeMotionCancel();
5176 secondWindow->consumeMotionDown();
5177
5178 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005179 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5180 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005181 // The first window gets no events and the second+spy get up
5182 firstWindow->assertNoEvents();
5183 spyWindow->consumeMotionUp();
5184 secondWindow->consumeMotionUp();
5185}
5186
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005187TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005189
5190 PointF touchPoint = {10, 10};
5191
5192 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005193 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005194 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5195 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005196 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005197 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005198 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5199 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005200 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005201
5202 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005203 mDispatcher->onWindowInfosChanged(
5204 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005205
5206 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005207 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5208 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5209 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005210 // Only the first window should get the down event
5211 firstWindow->consumeMotionDown();
5212 secondWindow->assertNoEvents();
5213
5214 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005215 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5216 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005217 // Only the first window should get the pointer down event
5218 firstWindow->consumeMotionPointerDown(1);
5219 secondWindow->assertNoEvents();
5220
5221 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005222 TransferFunction f = GetParam();
5223 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5224 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005225 // The first window gets cancel and the second gets down and pointer down
5226 firstWindow->consumeMotionCancel();
5227 secondWindow->consumeMotionDown();
5228 secondWindow->consumeMotionPointerDown(1);
5229
5230 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005231 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5232 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005233 // The first window gets nothing and the second gets pointer up
5234 firstWindow->assertNoEvents();
5235 secondWindow->consumeMotionPointerUp(1);
5236
5237 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005238 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5239 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005240 // The first window gets nothing and the second gets up
5241 firstWindow->assertNoEvents();
5242 secondWindow->consumeMotionUp();
5243}
5244
Arthur Hungc539dbb2022-12-08 07:45:36 +00005245TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5247
5248 // Create a couple of windows
5249 sp<FakeWindowHandle> firstWindow =
5250 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5251 ADISPLAY_ID_DEFAULT);
5252 firstWindow->setDupTouchToWallpaper(true);
5253 sp<FakeWindowHandle> secondWindow =
5254 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5255 ADISPLAY_ID_DEFAULT);
5256 secondWindow->setDupTouchToWallpaper(true);
5257
5258 sp<FakeWindowHandle> wallpaper1 =
5259 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5260 wallpaper1->setIsWallpaper(true);
5261
5262 sp<FakeWindowHandle> wallpaper2 =
5263 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5264 wallpaper2->setIsWallpaper(true);
5265 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005266 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5267 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5268 {},
5269 0,
5270 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005271
5272 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005273 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5274 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005275
5276 // Only the first window should get the down event
5277 firstWindow->consumeMotionDown();
5278 secondWindow->assertNoEvents();
5279 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5280 wallpaper2->assertNoEvents();
5281
5282 // Transfer touch focus to the second window
5283 TransferFunction f = GetParam();
5284 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5285 ASSERT_TRUE(success);
5286
5287 // The first window gets cancel and the second gets down
5288 firstWindow->consumeMotionCancel();
5289 secondWindow->consumeMotionDown();
5290 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5291 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5292
5293 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5295 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005296 // The first window gets no events and the second gets up
5297 firstWindow->assertNoEvents();
5298 secondWindow->consumeMotionUp();
5299 wallpaper1->assertNoEvents();
5300 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5301}
5302
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005303// For the cases of single pointer touch and two pointers non-split touch, the api's
5304// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5305// for the case where there are multiple pointers split across several windows.
5306INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5307 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005308 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5309 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005310 return dispatcher->transferTouch(destChannelToken,
5311 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005312 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005313 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5314 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005315 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005316 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005317 }));
5318
Svet Ganov5d3bc372020-01-26 23:11:07 -08005319TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005320 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005321
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005322 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005323 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5324 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005325 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005326
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005327 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005328 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5329 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005330 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005331
5332 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005333 mDispatcher->onWindowInfosChanged(
5334 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005335
5336 PointF pointInFirst = {300, 200};
5337 PointF pointInSecond = {300, 600};
5338
5339 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005340 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5341 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5342 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005343 // Only the first window should get the down event
5344 firstWindow->consumeMotionDown();
5345 secondWindow->assertNoEvents();
5346
5347 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005348 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5349 ADISPLAY_ID_DEFAULT,
5350 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005351 // The first window gets a move and the second a down
5352 firstWindow->consumeMotionMove();
5353 secondWindow->consumeMotionDown();
5354
5355 // Transfer touch focus to the second window
5356 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5357 // The first window gets cancel and the new gets pointer down (it already saw down)
5358 firstWindow->consumeMotionCancel();
5359 secondWindow->consumeMotionPointerDown(1);
5360
5361 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005362 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5363 ADISPLAY_ID_DEFAULT,
5364 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005365 // The first window gets nothing and the second gets pointer up
5366 firstWindow->assertNoEvents();
5367 secondWindow->consumeMotionPointerUp(1);
5368
5369 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005370 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5371 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005372 // The first window gets nothing and the second gets up
5373 firstWindow->assertNoEvents();
5374 secondWindow->consumeMotionUp();
5375}
5376
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005377// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5378// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5379// touch is not supported, so the touch should continue on those windows and the transferred-to
5380// window should get nothing.
5381TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5383
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005384 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005385 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5386 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005387 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005388
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005389 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005390 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5391 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005392 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005393
5394 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005395 mDispatcher->onWindowInfosChanged(
5396 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005397
5398 PointF pointInFirst = {300, 200};
5399 PointF pointInSecond = {300, 600};
5400
5401 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005402 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5403 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5404 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005405 // Only the first window should get the down event
5406 firstWindow->consumeMotionDown();
5407 secondWindow->assertNoEvents();
5408
5409 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005410 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5411 ADISPLAY_ID_DEFAULT,
5412 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005413 // The first window gets a move and the second a down
5414 firstWindow->consumeMotionMove();
5415 secondWindow->consumeMotionDown();
5416
5417 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005418 const bool transferred =
5419 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005420 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5421 ASSERT_FALSE(transferred);
5422 firstWindow->assertNoEvents();
5423 secondWindow->assertNoEvents();
5424
5425 // The rest of the dispatch should proceed as normal
5426 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005427 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5428 ADISPLAY_ID_DEFAULT,
5429 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005430 // The first window gets MOVE and the second gets pointer up
5431 firstWindow->consumeMotionMove();
5432 secondWindow->consumeMotionUp();
5433
5434 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005435 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5436 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005437 // The first window gets nothing and the second gets up
5438 firstWindow->consumeMotionUp();
5439 secondWindow->assertNoEvents();
5440}
5441
Arthur Hungabbb9d82021-09-01 14:52:30 +00005442// This case will create two windows and one mirrored window on the default display and mirror
5443// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5444// the windows info of second display before default display.
5445TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5447 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005448 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005449 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005450 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005451 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005452 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005453
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005454 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005455 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005456
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005457 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005458 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005459
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005460 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005461 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005462
5463 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005464 mDispatcher->onWindowInfosChanged(
5465 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5466 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5467 *secondWindowInPrimary->getInfo()},
5468 {},
5469 0,
5470 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005471
5472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005473 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005474 {50, 50}))
5475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5476
5477 // Window should receive motion event.
5478 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5479
5480 // Transfer touch focus
5481 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5482 secondWindowInPrimary->getToken()));
5483 // The first window gets cancel.
5484 firstWindowInPrimary->consumeMotionCancel();
5485 secondWindowInPrimary->consumeMotionDown();
5486
5487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005488 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005489 ADISPLAY_ID_DEFAULT, {150, 50}))
5490 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5491 firstWindowInPrimary->assertNoEvents();
5492 secondWindowInPrimary->consumeMotionMove();
5493
5494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005495 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005496 {150, 50}))
5497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5498 firstWindowInPrimary->assertNoEvents();
5499 secondWindowInPrimary->consumeMotionUp();
5500}
5501
5502// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5503// 'transferTouch' api.
5504TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5505 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5506 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005507 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005508 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005509 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005510 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005511 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005512
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005513 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005514 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005515
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005516 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005517 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005518
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005519 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005520 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005521
5522 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005523 mDispatcher->onWindowInfosChanged(
5524 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5525 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5526 *secondWindowInPrimary->getInfo()},
5527 {},
5528 0,
5529 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005530
5531 // Touch on second display.
5532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005533 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5534 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5536
5537 // Window should receive motion event.
5538 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5539
5540 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005541 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005542
5543 // The first window gets cancel.
5544 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5545 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5546
5547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005548 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005549 SECOND_DISPLAY_ID, {150, 50}))
5550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5551 firstWindowInPrimary->assertNoEvents();
5552 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5553
5554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005555 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5557 firstWindowInPrimary->assertNoEvents();
5558 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5559}
5560
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005561TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005562 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005563 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5564 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005565
Vishnu Nair47074b82020-08-14 11:54:47 -07005566 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005567 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005568 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005569
5570 window->consumeFocusEvent(true);
5571
Prabir Pradhan678438e2023-04-13 19:32:51 +00005572 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005573
5574 // Window should receive key down event.
5575 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005576
5577 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005578 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005579 mFakePolicy->assertUserActivityPoked();
5580}
5581
5582TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5585 "Fake Window", ADISPLAY_ID_DEFAULT);
5586
5587 window->setDisableUserActivity(true);
5588 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005589 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005590 setFocusedWindow(window);
5591
5592 window->consumeFocusEvent(true);
5593
5594 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5595
5596 // Window should receive key down event.
5597 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5598
5599 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005600 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005601 mFakePolicy->assertUserActivityNotPoked();
5602}
5603
5604TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5606 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5607 "Fake Window", ADISPLAY_ID_DEFAULT);
5608
5609 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005610 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005611 setFocusedWindow(window);
5612
5613 window->consumeFocusEvent(true);
5614
5615 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5616 mDispatcher->waitForIdle();
5617
5618 // System key is not passed down
5619 window->assertNoEvents();
5620
5621 // Should have poked user activity
5622 mFakePolicy->assertUserActivityPoked();
5623}
5624
5625TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5627 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5628 "Fake Window", ADISPLAY_ID_DEFAULT);
5629
5630 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005631 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005632 setFocusedWindow(window);
5633
5634 window->consumeFocusEvent(true);
5635
5636 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5637 mDispatcher->waitForIdle();
5638
5639 // System key is not passed down
5640 window->assertNoEvents();
5641
5642 // Should have poked user activity
5643 mFakePolicy->assertUserActivityPoked();
5644}
5645
5646TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5648 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5649 "Fake Window", ADISPLAY_ID_DEFAULT);
5650
5651 window->setDisableUserActivity(true);
5652 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005653 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005654 setFocusedWindow(window);
5655
5656 window->consumeFocusEvent(true);
5657
5658 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5659 mDispatcher->waitForIdle();
5660
5661 // System key is not passed down
5662 window->assertNoEvents();
5663
5664 // Should have poked user activity
5665 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005666}
5667
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005668TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5671 "Fake Window", ADISPLAY_ID_DEFAULT);
5672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005673 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005674
5675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005676 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005677 ADISPLAY_ID_DEFAULT, {100, 100}))
5678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5679
5680 window->consumeMotionEvent(
5681 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5682
5683 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005684 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005685 mFakePolicy->assertUserActivityPoked();
5686}
5687
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005688TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5691 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005692
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005693 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005694
Prabir Pradhan678438e2023-04-13 19:32:51 +00005695 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005696 mDispatcher->waitForIdle();
5697
5698 window->assertNoEvents();
5699}
5700
5701// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5702TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5705 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005706
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005707 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005708
5709 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005710 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005711 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005712 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5713 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005714
5715 // Window should receive only the motion event
5716 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5717 window->assertNoEvents(); // Key event or focus event will not be received
5718}
5719
arthurhungea3f4fc2020-12-21 23:18:53 +08005720TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5722
arthurhungea3f4fc2020-12-21 23:18:53 +08005723 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005724 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5725 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005726 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005727
arthurhungea3f4fc2020-12-21 23:18:53 +08005728 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005729 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5730 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005731 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005732
5733 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005734 mDispatcher->onWindowInfosChanged(
5735 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005736
5737 PointF pointInFirst = {300, 200};
5738 PointF pointInSecond = {300, 600};
5739
5740 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005741 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5742 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5743 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005744 // Only the first window should get the down event
5745 firstWindow->consumeMotionDown();
5746 secondWindow->assertNoEvents();
5747
5748 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005749 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5750 ADISPLAY_ID_DEFAULT,
5751 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005752 // The first window gets a move and the second a down
5753 firstWindow->consumeMotionMove();
5754 secondWindow->consumeMotionDown();
5755
5756 // Send pointer cancel to the second window
5757 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005758 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005759 {pointInFirst, pointInSecond});
5760 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005761 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005762 // The first window gets move and the second gets cancel.
5763 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5764 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5765
5766 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005767 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5768 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005769 // The first window gets up and the second gets nothing.
5770 firstWindow->consumeMotionUp();
5771 secondWindow->assertNoEvents();
5772}
5773
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005774TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5776
5777 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005778 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005779 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005780 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5781 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5782 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5783
Harry Cutts33476232023-01-30 19:57:29 +00005784 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005785 window->assertNoEvents();
5786 mDispatcher->waitForIdle();
5787}
5788
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005789using InputDispatcherMonitorTest = InputDispatcherTest;
5790
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005791/**
5792 * Two entities that receive touch: A window, and a global monitor.
5793 * The touch goes to the window, and then the window disappears.
5794 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5795 * for the monitor, as well.
5796 * 1. foregroundWindow
5797 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5798 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005799TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005800 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5801 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005802 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005803
Prabir Pradhanfb549072023-10-05 19:17:36 +00005804 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005805
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005806 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005808 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005809 {100, 200}))
5810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5811
5812 // Both the foreground window and the global monitor should receive the touch down
5813 window->consumeMotionDown();
5814 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5815
5816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005817 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005818 ADISPLAY_ID_DEFAULT, {110, 200}))
5819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5820
5821 window->consumeMotionMove();
5822 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5823
5824 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005825 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005826 window->consumeMotionCancel();
5827 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5828
5829 // If more events come in, there will be no more foreground window to send them to. This will
5830 // cause a cancel for the monitor, as well.
5831 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005832 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005833 ADISPLAY_ID_DEFAULT, {120, 200}))
5834 << "Injection should fail because the window was removed";
5835 window->assertNoEvents();
5836 // Global monitor now gets the cancel
5837 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5838}
5839
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005840TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5843 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005844 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005845
Prabir Pradhanfb549072023-10-05 19:17:36 +00005846 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005847
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005849 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005851 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005852 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005853}
5854
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005855TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005856 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005857
Chris Yea209fde2020-07-22 13:54:51 -07005858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005859 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5860 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005861 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005862
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005864 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005866 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005867 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005868
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005869 // Pilfer pointers from the monitor.
5870 // This should not do anything and the window should continue to receive events.
5871 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005872
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005874 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005875 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005877
5878 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5879 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005880}
5881
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005882TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005884 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5885 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005886 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005887 window->setWindowOffset(20, 40);
5888 window->setWindowTransform(0, 1, -1, 0);
5889
Prabir Pradhanfb549072023-10-05 19:17:36 +00005890 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005891
5892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005894 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5895 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5896 MotionEvent* event = monitor.consumeMotion();
5897 // Even though window has transform, gesture monitor must not.
5898 ASSERT_EQ(ui::Transform(), event->getTransform());
5899}
5900
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005901TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005903 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005904
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005905 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005906 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005907 << "Injection should fail if there is a monitor, but no touchable window";
5908 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005909}
5910
chaviw81e2bb92019-12-18 15:03:51 -08005911TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005913 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5914 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005915
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005916 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005917
5918 NotifyMotionArgs motionArgs =
5919 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5920 ADISPLAY_ID_DEFAULT);
5921
Prabir Pradhan678438e2023-04-13 19:32:51 +00005922 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005923 // Window should receive motion down event.
5924 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5925
5926 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005927 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005928 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5929 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5930 motionArgs.pointerCoords[0].getX() - 10);
5931
Prabir Pradhan678438e2023-04-13 19:32:51 +00005932 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005933 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005934 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005935}
5936
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005937/**
5938 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5939 * the device default right away. In the test scenario, we check both the default value,
5940 * and the action of enabling / disabling.
5941 */
5942TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005944 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5945 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005946 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005947
5948 // Set focused application.
5949 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005950 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005951
5952 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005953 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005954 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005955 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005956
5957 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005958 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005959 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005960 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005961
5962 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005963 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005964 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005965 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005966 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005968 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005969 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005970
5971 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005972 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005973 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005974 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005975
5976 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005977 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005978 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005979 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005980 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005981 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005982 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005983 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005984
5985 window->assertNoEvents();
5986}
5987
Gang Wange9087892020-01-07 12:17:14 -05005988TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005990 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5991 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005992
5993 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005994 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005996 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005997 setFocusedWindow(window);
5998
Harry Cutts33476232023-01-30 19:57:29 +00005999 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006000
Prabir Pradhan678438e2023-04-13 19:32:51 +00006001 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6002 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006003
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006004 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006005 ASSERT_NE(event, nullptr);
6006
6007 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6008 ASSERT_NE(verified, nullptr);
6009 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6010
6011 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6012 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6013 ASSERT_EQ(keyArgs.source, verified->source);
6014 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6015
6016 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6017
6018 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006019 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006020 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006021 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6022 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6023 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6024 ASSERT_EQ(0, verifiedKey.repeatCount);
6025}
6026
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006027TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006029 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6030 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006031
6032 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6033
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006034 ui::Transform transform;
6035 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6036
6037 gui::DisplayInfo displayInfo;
6038 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6039 displayInfo.transform = transform;
6040
Patrick Williamsd828f302023-04-28 17:52:08 -05006041 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006042
Prabir Pradhan678438e2023-04-13 19:32:51 +00006043 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006044 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6045 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006046 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006047
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006048 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006049 ASSERT_NE(event, nullptr);
6050
6051 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6052 ASSERT_NE(verified, nullptr);
6053 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6054
6055 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6056 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6057 EXPECT_EQ(motionArgs.source, verified->source);
6058 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6059
6060 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6061
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006062 const vec2 rawXY =
6063 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6064 motionArgs.pointerCoords[0].getXYValue());
6065 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6066 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006067 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006068 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006069 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006070 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6071 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6072}
6073
chaviw09c8d2d2020-08-24 15:48:26 -07006074/**
6075 * Ensure that separate calls to sign the same data are generating the same key.
6076 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6077 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6078 * tests.
6079 */
6080TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6081 KeyEvent event = getTestKeyEvent();
6082 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6083
6084 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6085 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6086 ASSERT_EQ(hmac1, hmac2);
6087}
6088
6089/**
6090 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6091 */
6092TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6093 KeyEvent event = getTestKeyEvent();
6094 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6095 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6096
6097 verifiedEvent.deviceId += 1;
6098 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6099
6100 verifiedEvent.source += 1;
6101 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6102
6103 verifiedEvent.eventTimeNanos += 1;
6104 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6105
6106 verifiedEvent.displayId += 1;
6107 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6108
6109 verifiedEvent.action += 1;
6110 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6111
6112 verifiedEvent.downTimeNanos += 1;
6113 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6114
6115 verifiedEvent.flags += 1;
6116 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6117
6118 verifiedEvent.keyCode += 1;
6119 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6120
6121 verifiedEvent.scanCode += 1;
6122 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6123
6124 verifiedEvent.metaState += 1;
6125 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6126
6127 verifiedEvent.repeatCount += 1;
6128 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6129}
6130
Vishnu Nair958da932020-08-21 17:12:37 -07006131TEST_F(InputDispatcherTest, SetFocusedWindow) {
6132 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6133 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006134 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006135 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006136 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006137 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6138
6139 // Top window is also focusable but is not granted focus.
6140 windowTop->setFocusable(true);
6141 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged(
6143 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006144 setFocusedWindow(windowSecond);
6145
6146 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006148 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006149
6150 // Focused window should receive event.
6151 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6152 windowTop->assertNoEvents();
6153}
6154
6155TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6157 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006158 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006159 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6160
6161 window->setFocusable(true);
6162 // Release channel for window is no longer valid.
6163 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006164 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006165 setFocusedWindow(window);
6166
6167 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006168 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006169
6170 // window channel is invalid, so it should not receive any input event.
6171 window->assertNoEvents();
6172}
6173
6174TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6176 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006177 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006178 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006179 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6180
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006181 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006182 setFocusedWindow(window);
6183
6184 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006185 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006186
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006187 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006188 window->assertNoEvents();
6189}
6190
6191TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6193 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006194 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006195 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006196 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006197 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6198
6199 windowTop->setFocusable(true);
6200 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006201 mDispatcher->onWindowInfosChanged(
6202 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006203 setFocusedWindow(windowTop);
6204 windowTop->consumeFocusEvent(true);
6205
Chavi Weingarten847e8512023-03-29 00:26:09 +00006206 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006207 mDispatcher->onWindowInfosChanged(
6208 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006209 windowSecond->consumeFocusEvent(true);
6210 windowTop->consumeFocusEvent(false);
6211
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006213 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006214
6215 // Focused window should receive event.
6216 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6217}
6218
Chavi Weingarten847e8512023-03-29 00:26:09 +00006219TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6221 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006222 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006223 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006224 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6226
6227 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006228 windowSecond->setFocusable(false);
6229 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006230 mDispatcher->onWindowInfosChanged(
6231 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006232 setFocusedWindow(windowTop);
6233 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006234
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006236 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006237
6238 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006239 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006240 windowSecond->assertNoEvents();
6241}
6242
6243TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6245 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006246 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006247 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006248 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6249 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006250 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6251
6252 window->setFocusable(true);
6253 previousFocusedWindow->setFocusable(true);
6254 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006255 mDispatcher->onWindowInfosChanged(
6256 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006257 setFocusedWindow(previousFocusedWindow);
6258 previousFocusedWindow->consumeFocusEvent(true);
6259
6260 // Requesting focus on invisible window takes focus from currently focused window.
6261 setFocusedWindow(window);
6262 previousFocusedWindow->consumeFocusEvent(false);
6263
6264 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006266 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6267 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006268
6269 // Window does not get focus event or key down.
6270 window->assertNoEvents();
6271
6272 // Window becomes visible.
6273 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006274 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006275
6276 // Window receives focus event.
6277 window->consumeFocusEvent(true);
6278 // Focused window receives key down.
6279 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6280}
6281
Vishnu Nair599f1412021-06-21 10:39:58 -07006282TEST_F(InputDispatcherTest, DisplayRemoved) {
6283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6284 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006285 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006286 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6287
6288 // window is granted focus.
6289 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006290 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006291 setFocusedWindow(window);
6292 window->consumeFocusEvent(true);
6293
6294 // When a display is removed window loses focus.
6295 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6296 window->consumeFocusEvent(false);
6297}
6298
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006299/**
6300 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6301 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6302 * of the 'slipperyEnterWindow'.
6303 *
6304 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6305 * a way so that the touched location is no longer covered by the top window.
6306 *
6307 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6308 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6309 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6310 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6311 * with ACTION_DOWN).
6312 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6313 * window moved itself away from the touched location and had Flag::SLIPPERY.
6314 *
6315 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6316 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6317 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6318 *
6319 * In this test, we ensure that the event received by the bottom window has
6320 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6321 */
6322TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006323 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006324 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006325
6326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6327 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6328
6329 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006330 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006331 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006332 // Make sure this one overlaps the bottom window
6333 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6334 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6335 // one. Windows with the same owner are not considered to be occluding each other.
6336 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6337
6338 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006339 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006340 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6341
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006342 mDispatcher->onWindowInfosChanged(
6343 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006344
6345 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006346 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6348 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006349 slipperyExitWindow->consumeMotionDown();
6350 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006351 mDispatcher->onWindowInfosChanged(
6352 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006353
Prabir Pradhan678438e2023-04-13 19:32:51 +00006354 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6355 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6356 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006357
6358 slipperyExitWindow->consumeMotionCancel();
6359
6360 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6361 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6362}
6363
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006364/**
6365 * Two windows, one on the left and another on the right. The left window is slippery. The right
6366 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6367 * touch moves from the left window into the right window, the gesture should continue to go to the
6368 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6369 * reproduces a crash.
6370 */
6371TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6373
6374 sp<FakeWindowHandle> leftSlipperyWindow =
6375 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6376 leftSlipperyWindow->setSlippery(true);
6377 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6378
6379 sp<FakeWindowHandle> rightDropTouchesWindow =
6380 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6381 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6382 rightDropTouchesWindow->setDropInput(true);
6383
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006384 mDispatcher->onWindowInfosChanged(
6385 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006386
6387 // Start touch in the left window
6388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6389 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6390 .build());
6391 leftSlipperyWindow->consumeMotionDown();
6392
6393 // And move it into the right window
6394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6395 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6396 .build());
6397
6398 // Since the right window isn't eligible to receive input, touch does not slip.
6399 // The left window continues to receive the gesture.
6400 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6401 rightDropTouchesWindow->assertNoEvents();
6402}
6403
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006404/**
6405 * A single window is on screen first. Touch is injected into that window. Next, a second window
6406 * appears. Since the first window is slippery, touch will move from the first window to the second.
6407 */
6408TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6410 sp<FakeWindowHandle> originalWindow =
6411 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6412 originalWindow->setFrame(Rect(0, 0, 200, 200));
6413 originalWindow->setSlippery(true);
6414
6415 sp<FakeWindowHandle> appearingWindow =
6416 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6417 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6418
6419 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6420
6421 // Touch down on the original window
6422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6423 injectMotionEvent(*mDispatcher,
6424 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6425 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6426 .build()));
6427 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6428
6429 // Now, a new window appears. This could be, for example, a notification shade that appears
6430 // after user starts to drag down on the launcher window.
6431 mDispatcher->onWindowInfosChanged(
6432 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6434 injectMotionEvent(*mDispatcher,
6435 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6436 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6437 .build()));
6438 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6439 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6441 injectMotionEvent(*mDispatcher,
6442 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6443 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6444 .build()));
6445 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6446
6447 originalWindow->assertNoEvents();
6448 appearingWindow->assertNoEvents();
6449}
6450
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006451TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006452 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6454
6455 sp<FakeWindowHandle> leftWindow =
6456 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6457 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006458 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006459
6460 sp<FakeWindowHandle> rightSpy =
6461 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6462 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006463 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006464 rightSpy->setSpy(true);
6465 rightSpy->setTrustedOverlay(true);
6466
6467 sp<FakeWindowHandle> rightWindow =
6468 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6469 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006470 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006471
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006472 mDispatcher->onWindowInfosChanged(
6473 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006474
6475 // Touch in the left window
6476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6477 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6478 .build());
6479 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6480 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006481 ASSERT_NO_FATAL_FAILURE(
6482 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006483
6484 // Touch another finger over the right windows
6485 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6486 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6487 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6488 .build());
6489 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6490 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6491 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6492 mDispatcher->waitForIdle();
6493 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006494 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6495 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006496
6497 // Release finger over left window. The UP actions are not treated as device interaction.
6498 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6499 // is part of the UP action, we do not treat this as device interaction.
6500 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6501 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6502 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6503 .build());
6504 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6505 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6506 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6507 mDispatcher->waitForIdle();
6508 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6509
6510 // Move remaining finger
6511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6512 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6513 .build());
6514 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6515 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6516 mDispatcher->waitForIdle();
6517 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006518 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006519
6520 // Release all fingers
6521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6522 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6523 .build());
6524 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6525 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6526 mDispatcher->waitForIdle();
6527 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6528}
6529
6530TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6532
6533 sp<FakeWindowHandle> window =
6534 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6535 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006536 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006537
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006538 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006539 setFocusedWindow(window);
6540 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6541
6542 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6543 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6544 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006545 ASSERT_NO_FATAL_FAILURE(
6546 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006547
6548 // The UP actions are not treated as device interaction.
6549 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6550 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6551 mDispatcher->waitForIdle();
6552 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6553}
6554
Prabir Pradhan5893d362023-11-17 04:30:40 +00006555TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6557
6558 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6559 ADISPLAY_ID_DEFAULT);
6560 left->setFrame(Rect(0, 0, 100, 100));
6561 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6562 "Right Window", ADISPLAY_ID_DEFAULT);
6563 right->setFrame(Rect(100, 0, 200, 100));
6564 sp<FakeWindowHandle> spy =
6565 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6566 spy->setFrame(Rect(0, 0, 200, 100));
6567 spy->setTrustedOverlay(true);
6568 spy->setSpy(true);
6569
6570 mDispatcher->onWindowInfosChanged(
6571 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6572
6573 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6574 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6575 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6576 mDispatcher->notifyMotion(notifyArgs);
6577
6578 const MotionEvent& leftEnter = left->consumeMotionEvent(
6579 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6580 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6581
6582 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6583 Not(WithEventId(notifyArgs.id)),
6584 Not(WithEventId(leftEnter.getId())),
6585 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6586
6587 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6588 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6589 {PointF{150, 50}});
6590 mDispatcher->notifyMotion(notifyArgs);
6591
6592 const MotionEvent& leftExit = left->consumeMotionEvent(
6593 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6594 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6595
6596 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6597 Not(WithEventId(notifyArgs.id)),
6598 Not(WithEventId(leftExit.getId())),
6599 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6600
6601 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6602}
6603
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006604class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6605protected:
6606 std::shared_ptr<FakeApplicationHandle> mApp;
6607 sp<FakeWindowHandle> mWindow;
6608
6609 virtual void SetUp() override {
6610 InputDispatcherTest::SetUp();
6611
6612 mApp = std::make_shared<FakeApplicationHandle>();
6613
6614 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6615 mWindow->setFrame(Rect(0, 0, 100, 100));
6616
6617 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6618 setFocusedWindow(mWindow);
6619 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6620 }
6621
6622 void setFallback(int32_t keycode) {
6623 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6624 return KeyEventBuilder(event).keyCode(keycode).build();
6625 });
6626 }
6627
6628 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6629 KeyEvent* event = mWindow->consumeKey(handled);
6630 ASSERT_NE(event, nullptr) << "Did not receive key event";
6631 ASSERT_THAT(*event, matcher);
6632 }
6633};
6634
6635TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6636 mDispatcher->notifyKey(
6637 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6638 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6639 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6640}
6641
6642TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6643 mDispatcher->notifyKey(
6644 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6645 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6646 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6647}
6648
6649TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6650 mDispatcher->notifyKey(
6651 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6652
6653 // Do not handle this key event.
6654 consumeKey(/*handled=*/false,
6655 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6656 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6657
6658 // Since the policy did not request any fallback to be generated, ensure there are no events.
6659 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6660}
6661
6662TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6663 setFallback(AKEYCODE_B);
6664 mDispatcher->notifyKey(
6665 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6666
6667 // Do not handle this key event.
6668 consumeKey(/*handled=*/false,
6669 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6670
6671 // Since the key was not handled, ensure the fallback event was dispatched instead.
6672 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6673 consumeKey(/*handled=*/true,
6674 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6675 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6676
6677 // Release the original key, and ensure the fallback key is also released.
6678 mDispatcher->notifyKey(
6679 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6680 consumeKey(/*handled=*/false,
6681 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6682 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6683 consumeKey(/*handled=*/true,
6684 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6685 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6686
6687 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6688 mWindow->assertNoEvents();
6689}
6690
6691TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6692 setFallback(AKEYCODE_B);
6693 mDispatcher->notifyKey(
6694 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6695
6696 // Do not handle this key event, but handle the fallback.
6697 consumeKey(/*handled=*/false,
6698 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6699 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6700 consumeKey(/*handled=*/true,
6701 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6702 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6703
6704 // Release the original key, and ensure the fallback key is also released.
6705 mDispatcher->notifyKey(
6706 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6707 // But this time, the app handles the original key.
6708 consumeKey(/*handled=*/true,
6709 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6710 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6711 // Ensure the fallback key is canceled.
6712 consumeKey(/*handled=*/true,
6713 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6714 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6715
6716 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6717 mWindow->assertNoEvents();
6718}
6719
6720TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6721 setFallback(AKEYCODE_B);
6722 mDispatcher->notifyKey(
6723 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6724
6725 // Do not handle this key event.
6726 consumeKey(/*handled=*/false,
6727 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6728 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6729 // App does not handle the fallback either, so ensure another fallback is not generated.
6730 setFallback(AKEYCODE_C);
6731 consumeKey(/*handled=*/false,
6732 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6733 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6734
6735 // Release the original key, and ensure the fallback key is also released.
6736 setFallback(AKEYCODE_B);
6737 mDispatcher->notifyKey(
6738 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6739 consumeKey(/*handled=*/false,
6740 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6741 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6742 consumeKey(/*handled=*/false,
6743 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6744 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6745
6746 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6747 mWindow->assertNoEvents();
6748}
6749
6750TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6751 setFallback(AKEYCODE_B);
6752 mDispatcher->notifyKey(
6753 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6754
6755 // Do not handle this key event, so fallback is generated.
6756 consumeKey(/*handled=*/false,
6757 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6758 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6759 consumeKey(/*handled=*/true,
6760 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6761 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6762
6763 // Release the original key, but assume the policy is misbehaving and it
6764 // generates an inconsistent fallback to the one from the DOWN event.
6765 setFallback(AKEYCODE_C);
6766 mDispatcher->notifyKey(
6767 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6768 consumeKey(/*handled=*/false,
6769 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6770 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6771 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6772 consumeKey(/*handled=*/true,
6773 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6774 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6775
6776 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6777 mWindow->assertNoEvents();
6778}
6779
6780TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6781 setFallback(AKEYCODE_B);
6782 mDispatcher->notifyKey(
6783 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6784
6785 // Do not handle this key event, so fallback is generated.
6786 consumeKey(/*handled=*/false,
6787 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6788 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6789 consumeKey(/*handled=*/true,
6790 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6791 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6792
6793 // The original key is canceled.
6794 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6795 .keyCode(AKEYCODE_A)
6796 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6797 .build());
6798 consumeKey(/*handled=*/false,
6799 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6800 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6801 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6802 // Ensure the fallback key is also canceled due to the original key being canceled.
6803 consumeKey(/*handled=*/true,
6804 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6805 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6806
6807 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6808 mWindow->assertNoEvents();
6809}
6810
Garfield Tan1c7bc862020-01-28 13:24:04 -08006811class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6812protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006813 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6814 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006815
Chris Yea209fde2020-07-22 13:54:51 -07006816 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006817 sp<FakeWindowHandle> mWindow;
6818
6819 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006820 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006821 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006822 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006823 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006824 ASSERT_EQ(OK, mDispatcher->start());
6825
6826 setUpWindow();
6827 }
6828
6829 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006830 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006831 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006832
Vishnu Nair47074b82020-08-14 11:54:47 -07006833 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006834 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006835 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006836 mWindow->consumeFocusEvent(true);
6837 }
6838
Chris Ye2ad95392020-09-01 13:44:44 -07006839 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006840 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006841 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006842 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006843 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006844
6845 // Window should receive key down event.
6846 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6847 }
6848
6849 void expectKeyRepeatOnce(int32_t repeatCount) {
6850 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006851 mWindow->consumeKeyEvent(
6852 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006853 }
6854
Chris Ye2ad95392020-09-01 13:44:44 -07006855 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006856 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006857 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006858 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006859 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006860
6861 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006862 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006863 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006864 }
6865};
6866
6867TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006868 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006869 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6870 expectKeyRepeatOnce(repeatCount);
6871 }
6872}
6873
6874TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006875 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006876 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6877 expectKeyRepeatOnce(repeatCount);
6878 }
Harry Cutts33476232023-01-30 19:57:29 +00006879 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006880 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006881 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6882 expectKeyRepeatOnce(repeatCount);
6883 }
6884}
6885
6886TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006887 sendAndConsumeKeyDown(/*deviceId=*/1);
6888 expectKeyRepeatOnce(/*repeatCount=*/1);
6889 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006890 mWindow->assertNoEvents();
6891}
6892
6893TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006894 sendAndConsumeKeyDown(/*deviceId=*/1);
6895 expectKeyRepeatOnce(/*repeatCount=*/1);
6896 sendAndConsumeKeyDown(/*deviceId=*/2);
6897 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006898 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006899 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006900 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006901 expectKeyRepeatOnce(/*repeatCount=*/2);
6902 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006903 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006904 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006905 mWindow->assertNoEvents();
6906}
6907
6908TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006909 sendAndConsumeKeyDown(/*deviceId=*/1);
6910 expectKeyRepeatOnce(/*repeatCount=*/1);
6911 sendAndConsumeKeyDown(/*deviceId=*/2);
6912 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006913 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006914 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006915 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006916 mWindow->assertNoEvents();
6917}
6918
liushenxiang42232912021-05-21 20:24:09 +08006919TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6920 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006921 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006922 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006923 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6924 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6925 mWindow->assertNoEvents();
6926}
6927
Garfield Tan1c7bc862020-01-28 13:24:04 -08006928TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006929 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006930 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006931 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006932 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006933 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6934 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6935 IdGenerator::getSource(repeatEvent->getId()));
6936 }
6937}
6938
6939TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006940 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006941 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006942
6943 std::unordered_set<int32_t> idSet;
6944 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006945 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006946 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6947 int32_t id = repeatEvent->getId();
6948 EXPECT_EQ(idSet.end(), idSet.find(id));
6949 idSet.insert(id);
6950 }
6951}
6952
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006953/* Test InputDispatcher for MultiDisplay */
6954class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6955public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006956 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006957 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006958
Chris Yea209fde2020-07-22 13:54:51 -07006959 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006960 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006961 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006962
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006963 // Set focus window for primary display, but focused display would be second one.
6964 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006965 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006966 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6967
Vishnu Nair958da932020-08-21 17:12:37 -07006968 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006969 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006970
Chris Yea209fde2020-07-22 13:54:51 -07006971 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006972 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006973 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006974 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006975 // Set focus display to second one.
6976 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6977 // Set focus window for second display.
6978 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006979 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006980 mDispatcher->onWindowInfosChanged(
6981 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006982 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006983 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006984 }
6985
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006986 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006987 InputDispatcherTest::TearDown();
6988
Chris Yea209fde2020-07-22 13:54:51 -07006989 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006990 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006991 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006992 windowInSecondary.clear();
6993 }
6994
6995protected:
Chris Yea209fde2020-07-22 13:54:51 -07006996 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006997 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006998 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006999 sp<FakeWindowHandle> windowInSecondary;
7000};
7001
7002TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7003 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007005 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007007 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007008 windowInSecondary->assertNoEvents();
7009
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007010 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007012 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007014 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007015 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007016}
7017
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007018TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007019 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007021 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007022 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007023 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007024 windowInSecondary->assertNoEvents();
7025
7026 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007028 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007029 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007030 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007031
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007032 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007033 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007034
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007035 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007036 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007037 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007038
7039 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007040 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007041 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007042 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007043 windowInSecondary->assertNoEvents();
7044}
7045
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007046// Test per-display input monitors for motion event.
7047TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007048 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007049 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007050 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007051 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007052
7053 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007057 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007058 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007059 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007060 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007061
7062 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007064 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007066 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007067 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007068 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007069 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007070
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007071 // Lift up the touch from the second display
7072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007073 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7075 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7076 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7077
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007078 // Test inject a non-pointer motion event.
7079 // If specific a display, it will dispatch to the focused window of particular display,
7080 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007082 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007084 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007085 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007086 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007087 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007088}
7089
7090// Test per-display input monitors for key event.
7091TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007092 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007093 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007094 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007095 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007096 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007097
7098 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007100 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007101 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007102 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007103 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007104 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007105}
7106
Vishnu Nair958da932020-08-21 17:12:37 -07007107TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7108 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007109 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007110 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007111 mDispatcher->onWindowInfosChanged(
7112 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7113 *windowInSecondary->getInfo()},
7114 {},
7115 0,
7116 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007117 setFocusedWindow(secondWindowInPrimary);
7118 windowInPrimary->consumeFocusEvent(false);
7119 secondWindowInPrimary->consumeFocusEvent(true);
7120
7121 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7123 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007124 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007125 windowInPrimary->assertNoEvents();
7126 windowInSecondary->assertNoEvents();
7127 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7128}
7129
Arthur Hungdfd528e2021-12-08 13:23:04 +00007130TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7131 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007132 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007133 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007134 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007135
7136 // Test touch down on primary display.
7137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007138 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7140 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7141 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7142
7143 // Test touch down on second display.
7144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007145 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7147 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7148 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7149
7150 // Trigger cancel touch.
7151 mDispatcher->cancelCurrentTouch();
7152 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7153 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7154 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7155 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7156
7157 // Test inject a move motion event, no window/monitor should receive the event.
7158 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007159 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007160 ADISPLAY_ID_DEFAULT, {110, 200}))
7161 << "Inject motion event should return InputEventInjectionResult::FAILED";
7162 windowInPrimary->assertNoEvents();
7163 monitorInPrimary.assertNoEvents();
7164
7165 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007166 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007167 SECOND_DISPLAY_ID, {110, 200}))
7168 << "Inject motion event should return InputEventInjectionResult::FAILED";
7169 windowInSecondary->assertNoEvents();
7170 monitorInSecondary.assertNoEvents();
7171}
7172
Jackal Guof9696682018-10-05 12:23:23 +08007173class InputFilterTest : public InputDispatcherTest {
7174protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007175 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7176 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007177 NotifyMotionArgs motionArgs;
7178
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007179 motionArgs =
7180 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007181 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007182 motionArgs =
7183 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007184 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007185 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007186 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007187 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007188 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007189 } else {
7190 mFakePolicy->assertFilterInputEventWasNotCalled();
7191 }
7192 }
7193
7194 void testNotifyKey(bool expectToBeFiltered) {
7195 NotifyKeyArgs keyArgs;
7196
7197 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007198 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007199 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007200 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007201 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007202
7203 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007204 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007205 } else {
7206 mFakePolicy->assertFilterInputEventWasNotCalled();
7207 }
7208 }
7209};
7210
7211// Test InputFilter for MotionEvent
7212TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7213 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007214 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7215 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007216
7217 // Enable InputFilter
7218 mDispatcher->setInputFilterEnabled(true);
7219 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007220 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7221 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007222
7223 // Disable InputFilter
7224 mDispatcher->setInputFilterEnabled(false);
7225 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007226 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7227 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007228}
7229
7230// Test InputFilter for KeyEvent
7231TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7232 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007233 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007234
7235 // Enable InputFilter
7236 mDispatcher->setInputFilterEnabled(true);
7237 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007238 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007239
7240 // Disable InputFilter
7241 mDispatcher->setInputFilterEnabled(false);
7242 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007243 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007244}
7245
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007246// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7247// logical display coordinate space.
7248TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7249 ui::Transform firstDisplayTransform;
7250 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7251 ui::Transform secondDisplayTransform;
7252 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7253
7254 std::vector<gui::DisplayInfo> displayInfos(2);
7255 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7256 displayInfos[0].transform = firstDisplayTransform;
7257 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7258 displayInfos[1].transform = secondDisplayTransform;
7259
Patrick Williamsd828f302023-04-28 17:52:08 -05007260 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007261
7262 // Enable InputFilter
7263 mDispatcher->setInputFilterEnabled(true);
7264
7265 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007266 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7267 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007268}
7269
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007270class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7271protected:
7272 virtual void SetUp() override {
7273 InputDispatcherTest::SetUp();
7274
7275 /**
7276 * We don't need to enable input filter to test the injected event policy, but we enabled it
7277 * here to make the tests more realistic, since this policy only matters when inputfilter is
7278 * on.
7279 */
7280 mDispatcher->setInputFilterEnabled(true);
7281
7282 std::shared_ptr<InputApplicationHandle> application =
7283 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007284 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7285 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007286
7287 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7288 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007289 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007290 setFocusedWindow(mWindow);
7291 mWindow->consumeFocusEvent(true);
7292 }
7293
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007294 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7295 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007296 KeyEvent event;
7297
7298 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7299 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7300 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007301 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007302 const int32_t additionalPolicyFlags =
7303 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007305 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007306 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007307 policyFlags | additionalPolicyFlags));
7308
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007309 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007310 }
7311
7312 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7313 int32_t flags) {
7314 MotionEvent event;
7315 PointerProperties pointerProperties[1];
7316 PointerCoords pointerCoords[1];
7317 pointerProperties[0].clear();
7318 pointerProperties[0].id = 0;
7319 pointerCoords[0].clear();
7320 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7321 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7322
7323 ui::Transform identityTransform;
7324 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7325 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7326 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7327 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7328 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007329 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007330 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007331 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007332
7333 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007335 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007336 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007337 policyFlags | additionalPolicyFlags));
7338
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007339 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007340 }
7341
7342private:
7343 sp<FakeWindowHandle> mWindow;
7344};
7345
7346TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007347 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7348 // filter. Without it, the event will no different from a regularly injected event, and the
7349 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007350 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7351 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007352}
7353
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007354TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007355 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007356 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007357 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7358}
7359
7360TEST_F(InputFilterInjectionPolicyTest,
7361 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7362 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007363 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007364 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007365}
7366
7367TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007368 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7369 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007370}
7371
chaviwfd6d3512019-03-25 13:23:49 -07007372class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007373 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007374 InputDispatcherTest::SetUp();
7375
Chris Yea209fde2020-07-22 13:54:51 -07007376 std::shared_ptr<FakeApplicationHandle> application =
7377 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007378 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007379 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007380 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007381
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007382 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007383 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007384 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007385
7386 // Set focused application.
7387 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007388 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007389
7390 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007391 mDispatcher->onWindowInfosChanged(
7392 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007393 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007394 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007395 }
7396
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007397 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007398 InputDispatcherTest::TearDown();
7399
7400 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007401 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007402 }
7403
7404protected:
7405 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007406 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007407 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007408};
7409
7410// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7411// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7412// the onPointerDownOutsideFocus callback.
7413TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007416 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007417 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007418 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007419
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007420 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007421 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7422}
7423
7424// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7425// DOWN on the window that doesn't have focus. Ensure no window received the
7426// onPointerDownOutsideFocus callback.
7427TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007429 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7430 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007432 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007433
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007434 ASSERT_TRUE(mDispatcher->waitForIdle());
7435 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007436}
7437
7438// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7439// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7440TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007442 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007443 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007444 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007445
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007446 ASSERT_TRUE(mDispatcher->waitForIdle());
7447 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007448}
7449
7450// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7451// DOWN on the window that already has focus. Ensure no window received the
7452// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007453TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007455 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007456 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007458 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007459
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007460 ASSERT_TRUE(mDispatcher->waitForIdle());
7461 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007462}
7463
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007464// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7465// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7466TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7467 const MotionEvent event =
7468 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7469 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007470 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007471 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7472 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7475 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7476
7477 ASSERT_TRUE(mDispatcher->waitForIdle());
7478 mFakePolicy->assertOnPointerDownWasNotCalled();
7479 // Ensure that the unfocused window did not receive any FOCUS events.
7480 mUnfocusedWindow->assertNoEvents();
7481}
7482
chaviwaf87b3e2019-10-01 16:59:28 -07007483// These tests ensures we can send touch events to a single client when there are multiple input
7484// windows that point to the same client token.
7485class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7486 virtual void SetUp() override {
7487 InputDispatcherTest::SetUp();
7488
Chris Yea209fde2020-07-22 13:54:51 -07007489 std::shared_ptr<FakeApplicationHandle> application =
7490 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007491 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7492 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007493 mWindow1->setFrame(Rect(0, 0, 100, 100));
7494
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007495 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7496 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007497 mWindow2->setFrame(Rect(100, 100, 200, 200));
7498
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007499 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007500 }
7501
7502protected:
7503 sp<FakeWindowHandle> mWindow1;
7504 sp<FakeWindowHandle> mWindow2;
7505
7506 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007507 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007508 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7509 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007510 }
7511
7512 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7513 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007514 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007515 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007516
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007517 ASSERT_NE(nullptr, motionEvent)
7518 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007519
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007520 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007521 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007522
7523 for (size_t i = 0; i < points.size(); i++) {
7524 float expectedX = points[i].x;
7525 float expectedY = points[i].y;
7526
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007527 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007528 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007529 << ", got " << motionEvent->getX(i);
7530 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007531 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007532 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007533 }
7534 }
chaviw9eaa22c2020-07-01 16:21:27 -07007535
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007536 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007537 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007538 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7539 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007540
7541 // Always consume from window1 since it's the window that has the InputReceiver
7542 consumeMotionEvent(mWindow1, action, expectedPoints);
7543 }
chaviwaf87b3e2019-10-01 16:59:28 -07007544};
7545
7546TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7547 // Touch Window 1
7548 PointF touchedPoint = {10, 10};
7549 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007550 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007551
7552 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007553 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007554
7555 // Touch Window 2
7556 touchedPoint = {150, 150};
7557 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007558 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007559}
7560
chaviw9eaa22c2020-07-01 16:21:27 -07007561TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7562 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007563 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007564 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007565
7566 // Touch Window 1
7567 PointF touchedPoint = {10, 10};
7568 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007569 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007570 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007571 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007572
7573 // Touch Window 2
7574 touchedPoint = {150, 150};
7575 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007576 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7577 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007578
chaviw9eaa22c2020-07-01 16:21:27 -07007579 // Update the transform so rotation is set
7580 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007581 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007582 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7583 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007584}
7585
chaviw9eaa22c2020-07-01 16:21:27 -07007586TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007587 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007588 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007589
7590 // Touch Window 1
7591 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7592 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007593 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007594
7595 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007596 touchedPoints.push_back(PointF{150, 150});
7597 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007598 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007599
chaviw9eaa22c2020-07-01 16:21:27 -07007600 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007601 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007602 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007603
chaviw9eaa22c2020-07-01 16:21:27 -07007604 // Update the transform so rotation is set for Window 2
7605 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007606 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007607 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007608 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007609}
7610
chaviw9eaa22c2020-07-01 16:21:27 -07007611TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007612 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007613 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007614
7615 // Touch Window 1
7616 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7617 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007618 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007619
7620 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007621 touchedPoints.push_back(PointF{150, 150});
7622 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007623
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007624 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007625
7626 // Move both windows
7627 touchedPoints = {{20, 20}, {175, 175}};
7628 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7629 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7630
chaviw9eaa22c2020-07-01 16:21:27 -07007631 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007632
chaviw9eaa22c2020-07-01 16:21:27 -07007633 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007634 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007635 expectedPoints.pop_back();
7636
7637 // Touch Window 2
7638 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007639 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007640 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007641 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007642
7643 // Move both windows
7644 touchedPoints = {{20, 20}, {175, 175}};
7645 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7646 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7647
7648 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007649}
7650
7651TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7652 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007653 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007654
7655 // Touch Window 1
7656 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7657 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007658 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007659
7660 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007661 touchedPoints.push_back(PointF{150, 150});
7662 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007663
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007664 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007665
7666 // Move both windows
7667 touchedPoints = {{20, 20}, {175, 175}};
7668 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7669 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7670
chaviw9eaa22c2020-07-01 16:21:27 -07007671 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007672}
7673
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007674/**
7675 * When one of the windows is slippery, the touch should not slip into the other window with the
7676 * same input channel.
7677 */
7678TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7679 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007680 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007681
7682 // Touch down in window 1
7683 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7684 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7685 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7686
7687 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7688 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7689 // getting generated.
7690 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7691 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7692
7693 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7694}
7695
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007696/**
7697 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7698 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7699 * that the pointer is hovering over may have a different transform.
7700 */
7701TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007702 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007703
7704 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007705 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7706 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7707 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007708 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7709 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007710 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007711 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7712 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7713 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007714 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7715 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7716 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7717}
7718
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007719class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7720 virtual void SetUp() override {
7721 InputDispatcherTest::SetUp();
7722
Chris Yea209fde2020-07-22 13:54:51 -07007723 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007724 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007725 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7726 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007727 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007728 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007729 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007730
7731 // Set focused application.
7732 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7733
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007734 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007735 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007736 mWindow->consumeFocusEvent(true);
7737 }
7738
7739 virtual void TearDown() override {
7740 InputDispatcherTest::TearDown();
7741 mWindow.clear();
7742 }
7743
7744protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007745 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007746 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007747 sp<FakeWindowHandle> mWindow;
7748 static constexpr PointF WINDOW_LOCATION = {20, 20};
7749
7750 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007751 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7752 .x(WINDOW_LOCATION.x)
7753 .y(WINDOW_LOCATION.y);
7754 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7755 .pointer(touchingPointer)
7756 .build());
7757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7758 .pointer(touchingPointer)
7759 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007760 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007761
7762 sp<FakeWindowHandle> addSpyWindow() {
7763 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007764 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007765 spy->setTrustedOverlay(true);
7766 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007767 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007768 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007769 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007770 return spy;
7771 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007772};
7773
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007774// Send a tap and respond, which should not cause an ANR.
7775TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7776 tapOnWindow();
7777 mWindow->consumeMotionDown();
7778 mWindow->consumeMotionUp();
7779 ASSERT_TRUE(mDispatcher->waitForIdle());
7780 mFakePolicy->assertNotifyAnrWasNotCalled();
7781}
7782
7783// Send a regular key and respond, which should not cause an ANR.
7784TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007786 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7787 ASSERT_TRUE(mDispatcher->waitForIdle());
7788 mFakePolicy->assertNotifyAnrWasNotCalled();
7789}
7790
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007791TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7792 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007793 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007794 mWindow->consumeFocusEvent(false);
7795
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007796 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007797 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7798 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007799 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007801 // Key will not go to window because we have no focused window.
7802 // The 'no focused window' ANR timer should start instead.
7803
7804 // Now, the focused application goes away.
7805 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7806 // The key should get dropped and there should be no ANR.
7807
7808 ASSERT_TRUE(mDispatcher->waitForIdle());
7809 mFakePolicy->assertNotifyAnrWasNotCalled();
7810}
7811
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007812// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007813// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7814// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007815TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007817 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007818 WINDOW_LOCATION));
7819
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007820 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7821 ASSERT_TRUE(sequenceNum);
7822 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007823 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007824
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007825 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007826 mWindow->consumeMotionEvent(
7827 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007828 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007829 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007830}
7831
7832// Send a key to the app and have the app not respond right away.
7833TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7834 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007836 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7837 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007838 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007839 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007840 ASSERT_TRUE(mDispatcher->waitForIdle());
7841}
7842
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007843// We have a focused application, but no focused window
7844TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007845 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007846 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007847 mWindow->consumeFocusEvent(false);
7848
7849 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007851 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007852 WINDOW_LOCATION));
7853 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7854 mDispatcher->waitForIdle();
7855 mFakePolicy->assertNotifyAnrWasNotCalled();
7856
7857 // Once a focused event arrives, we get an ANR for this application
7858 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7859 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007860 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007861 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007862 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007863 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007864 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007865 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007866 ASSERT_TRUE(mDispatcher->waitForIdle());
7867}
7868
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007869/**
7870 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7871 * there will not be an ANR.
7872 */
7873TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7874 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007875 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007876 mWindow->consumeFocusEvent(false);
7877
7878 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007879 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7880 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007881 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7882 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7883
7884 // Define a valid key down event that is stale (too old).
7885 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007886 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007887 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007888
7889 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7890
7891 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007892 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007893 InputEventInjectionSync::WAIT_FOR_RESULT,
7894 INJECT_EVENT_TIMEOUT, policyFlags);
7895 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7896 << "Injection should fail because the event is stale";
7897
7898 ASSERT_TRUE(mDispatcher->waitForIdle());
7899 mFakePolicy->assertNotifyAnrWasNotCalled();
7900 mWindow->assertNoEvents();
7901}
7902
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007903// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007904// Make sure that we don't notify policy twice about the same ANR.
7905TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007906 const std::chrono::duration appTimeout = 400ms;
7907 mApplication->setDispatchingTimeout(appTimeout);
7908 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7909
Vishnu Nair47074b82020-08-14 11:54:47 -07007910 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007911 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007912 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007913
7914 // Once a focused event arrives, we get an ANR for this application
7915 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7916 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007917 const std::chrono::duration eventInjectionTimeout = 100ms;
7918 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007919 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007920 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007921 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7922 /*allowKeyRepeat=*/false);
7923 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7924 << "result=" << ftl::enum_string(result);
7925 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7926 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7927 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7928 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007929
Vishnu Naire4df8752022-09-08 09:17:55 -07007930 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007931 // ANR should not be raised again. It is up to policy to do that if it desires.
7932 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007933
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007934 // If we now get a focused window, the ANR should stop, but the policy handles that via
7935 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936 ASSERT_TRUE(mDispatcher->waitForIdle());
7937}
7938
7939// We have a focused application, but no focused window
7940TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007941 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007942 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007943 mWindow->consumeFocusEvent(false);
7944
7945 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007946 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007947
Vishnu Naire4df8752022-09-08 09:17:55 -07007948 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7949 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007950
7951 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007952 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007953 ASSERT_TRUE(mDispatcher->waitForIdle());
7954 mWindow->assertNoEvents();
7955}
7956
7957/**
7958 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7959 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7960 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7961 * the ANR mechanism should still work.
7962 *
7963 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7964 * DOWN event, while not responding on the second one.
7965 */
7966TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7967 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007968 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007969 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7970 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7971 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007972 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007973
7974 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007975 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007976 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7977 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7978 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007979 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007980
7981 // We have now sent down and up. Let's consume first event and then ANR on the second.
7982 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7983 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007984 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007985}
7986
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007987// A spy window can receive an ANR
7988TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7989 sp<FakeWindowHandle> spy = addSpyWindow();
7990
7991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007992 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007993 WINDOW_LOCATION));
7994 mWindow->consumeMotionDown();
7995
7996 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7997 ASSERT_TRUE(sequenceNum);
7998 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007999 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008000
8001 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008002 spy->consumeMotionEvent(
8003 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008004 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008005 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008006}
8007
8008// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008009// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008010TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8011 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008012
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008014 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008015 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008017
8018 // Stuck on the ACTION_UP
8019 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008020 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008022 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008023 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008024 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8025 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008026
8027 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8028 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008029 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008030 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008031 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008032}
8033
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008034// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008035// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008036TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8037 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008038
8039 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008040 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8041 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008042
8043 mWindow->consumeMotionDown();
8044 // Stuck on the ACTION_UP
8045 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008046 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008047
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008048 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008049 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008050 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8051 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008052
8053 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8054 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008055 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008056 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008057 spy->assertNoEvents();
8058}
8059
8060TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008061 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008062
Prabir Pradhanfb549072023-10-05 19:17:36 +00008063 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008064
8065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008066 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008067 WINDOW_LOCATION));
8068
8069 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8070 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8071 ASSERT_TRUE(consumeSeq);
8072
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008073 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8074 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008075
8076 monitor.finishEvent(*consumeSeq);
8077 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8078
8079 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008080 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008081}
8082
8083// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8084// process events, you don't get an anr. When the window later becomes unresponsive again, you
8085// get an ANR again.
8086// 1. tap -> block on ACTION_UP -> receive ANR
8087// 2. consume all pending events (= queue becomes healthy again)
8088// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8089TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8090 tapOnWindow();
8091
8092 mWindow->consumeMotionDown();
8093 // Block on ACTION_UP
8094 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008095 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008096 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8097 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008098 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008099 mWindow->assertNoEvents();
8100
8101 tapOnWindow();
8102 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008103 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008104 mWindow->consumeMotionUp();
8105
8106 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008107 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008108 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008109 mWindow->assertNoEvents();
8110}
8111
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008112// If a connection remains unresponsive for a while, make sure policy is only notified once about
8113// it.
8114TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008116 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008117 WINDOW_LOCATION));
8118
8119 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008120 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008121 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008122 // 'notifyConnectionUnresponsive' should only be called once per connection
8123 mFakePolicy->assertNotifyAnrWasNotCalled();
8124 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008125 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008126 mWindow->consumeMotionEvent(
8127 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008128 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008129 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008130 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008131 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008132}
8133
8134/**
8135 * 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 -07008136 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008137 *
8138 * Warning!!!
8139 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8140 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008141 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008142 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8143 *
8144 * If that value changes, this test should also change.
8145 */
8146TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8147 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008148 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008149
8150 tapOnWindow();
8151 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8152 ASSERT_TRUE(downSequenceNum);
8153 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8154 ASSERT_TRUE(upSequenceNum);
8155 // Don't finish the events yet, and send a key
8156 // Injection will "succeed" because we will eventually give up and send the key to the focused
8157 // window even if motions are still being processed. But because the injection timeout is short,
8158 // we will receive INJECTION_TIMED_OUT as the result.
8159
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008160 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008161 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8162 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008163 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008164 // Key will not be sent to the window, yet, because the window is still processing events
8165 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008166 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8167 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8168 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8169 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008170
8171 std::this_thread::sleep_for(500ms);
8172 // if we wait long enough though, dispatcher will give up, and still send the key
8173 // to the focused window, even though we have not yet finished the motion event
8174 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8175 mWindow->finishEvent(*downSequenceNum);
8176 mWindow->finishEvent(*upSequenceNum);
8177}
8178
8179/**
8180 * If a window is processing a motion event, and then a key event comes in, the key event should
8181 * not go to the focused window until the motion is processed.
8182 * If then a new motion comes in, then the pending key event should be going to the currently
8183 * focused window right away.
8184 */
8185TEST_F(InputDispatcherSingleWindowAnr,
8186 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8187 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008188 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008189
8190 tapOnWindow();
8191 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8192 ASSERT_TRUE(downSequenceNum);
8193 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8194 ASSERT_TRUE(upSequenceNum);
8195 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008196 mDispatcher->notifyKey(
8197 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8198 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8199 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008200 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008201 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8202 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8203 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8204 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008205
8206 // Now tap down again. It should cause the pending key to go to the focused window right away.
8207 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008208 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8209 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008210 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8211 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008212 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8213 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008214 mWindow->assertNoEvents();
8215}
8216
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008217/**
8218 * Send an event to the app and have the app not respond right away.
8219 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8220 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8221 * At some point, the window becomes responsive again.
8222 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8223 */
8224TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8226 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8227 .build());
8228
8229 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8230 ASSERT_TRUE(sequenceNum);
8231 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8232 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8233
8234 mWindow->finishEvent(*sequenceNum);
8235 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8236 ASSERT_TRUE(mDispatcher->waitForIdle());
8237 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8238
8239 // Now that the window is responsive, let's continue the gesture.
8240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8241 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8242 .build());
8243
8244 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8245 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8246 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8247 .build());
8248
8249 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8250 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8251 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8252 .build());
8253 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8254 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8255 .build());
8256 // We already canceled this pointer, so the window shouldn't get any new events.
8257 mWindow->assertNoEvents();
8258
8259 // Start another one.
8260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8261 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8262 .build());
8263 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8264}
8265
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008266class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8267 virtual void SetUp() override {
8268 InputDispatcherTest::SetUp();
8269
Chris Yea209fde2020-07-22 13:54:51 -07008270 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008271 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008272 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8273 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008274 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008275 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008276 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008277
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008278 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8279 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008280 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008281 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008282
8283 // Set focused application.
8284 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008285 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008286
8287 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008288 mDispatcher->onWindowInfosChanged(
8289 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008290 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008291 mFocusedWindow->consumeFocusEvent(true);
8292 }
8293
8294 virtual void TearDown() override {
8295 InputDispatcherTest::TearDown();
8296
8297 mUnfocusedWindow.clear();
8298 mFocusedWindow.clear();
8299 }
8300
8301protected:
Chris Yea209fde2020-07-22 13:54:51 -07008302 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008303 sp<FakeWindowHandle> mUnfocusedWindow;
8304 sp<FakeWindowHandle> mFocusedWindow;
8305 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8306 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8307 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8308
8309 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8310
8311 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8312
8313private:
8314 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008316 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008317 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008319 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008320 location));
8321 }
8322};
8323
8324// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8325// should be ANR'd first.
8326TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008328 injectMotionEvent(*mDispatcher,
8329 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8330 AINPUT_SOURCE_TOUCHSCREEN)
8331 .pointer(PointerBuilder(0, ToolType::FINGER)
8332 .x(FOCUSED_WINDOW_LOCATION.x)
8333 .y(FOCUSED_WINDOW_LOCATION.y))
8334 .build()));
8335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8336 injectMotionEvent(*mDispatcher,
8337 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8338 AINPUT_SOURCE_TOUCHSCREEN)
8339 .pointer(PointerBuilder(0, ToolType::FINGER)
8340 .x(FOCUSED_WINDOW_LOCATION.x)
8341 .y(FOCUSED_WINDOW_LOCATION.y))
8342 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008343 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008344 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008345 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008346 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008347 // We consumed all events, so no ANR
8348 ASSERT_TRUE(mDispatcher->waitForIdle());
8349 mFakePolicy->assertNotifyAnrWasNotCalled();
8350
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008352 injectMotionEvent(*mDispatcher,
8353 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8354 AINPUT_SOURCE_TOUCHSCREEN)
8355 .pointer(PointerBuilder(0, ToolType::FINGER)
8356 .x(FOCUSED_WINDOW_LOCATION.x)
8357 .y(FOCUSED_WINDOW_LOCATION.y))
8358 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008359 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8360 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008361
8362 const std::chrono::duration timeout =
8363 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008364 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008365
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008366 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008367 mFocusedWindow->consumeMotionDown();
8368 // This cancel is generated because the connection was unresponsive
8369 mFocusedWindow->consumeMotionCancel();
8370 mFocusedWindow->assertNoEvents();
8371 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008372 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008373 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8374 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008375 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008376}
8377
8378// If we have 2 windows with identical timeouts that are both unresponsive,
8379// it doesn't matter which order they should have ANR.
8380// But we should receive ANR for both.
8381TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8382 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008383 mUnfocusedWindow->setDispatchingTimeout(
8384 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008385 mDispatcher->onWindowInfosChanged(
8386 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008387
8388 tapOnFocusedWindow();
8389 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008390 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008391 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8392 mFocusedWindow->getDispatchingTimeout(
8393 DISPATCHING_TIMEOUT)),
8394 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8395
8396 ASSERT_THAT(anrConnectionTokens,
8397 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8398 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008399
8400 ASSERT_TRUE(mDispatcher->waitForIdle());
8401 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008402
8403 mFocusedWindow->consumeMotionDown();
8404 mFocusedWindow->consumeMotionUp();
8405 mUnfocusedWindow->consumeMotionOutside();
8406
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008407 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8408 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008409
8410 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008411 ASSERT_THAT(responsiveTokens,
8412 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8413 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008414 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008415}
8416
8417// If a window is already not responding, the second tap on the same window should be ignored.
8418// We should also log an error to account for the dropped event (not tested here).
8419// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8420TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8421 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008422 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008423 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008424 // Receive the events, but don't respond
8425 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8426 ASSERT_TRUE(downEventSequenceNum);
8427 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8428 ASSERT_TRUE(upEventSequenceNum);
8429 const std::chrono::duration timeout =
8430 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008431 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008432
8433 // Tap once again
8434 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008435 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008436 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008437 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008438 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008439 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008440 FOCUSED_WINDOW_LOCATION));
8441 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8442 // valid touch target
8443 mUnfocusedWindow->assertNoEvents();
8444
8445 // Consume the first tap
8446 mFocusedWindow->finishEvent(*downEventSequenceNum);
8447 mFocusedWindow->finishEvent(*upEventSequenceNum);
8448 ASSERT_TRUE(mDispatcher->waitForIdle());
8449 // The second tap did not go to the focused window
8450 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008451 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008452 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8453 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008454 mFakePolicy->assertNotifyAnrWasNotCalled();
8455}
8456
8457// If you tap outside of all windows, there will not be ANR
8458TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008459 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008460 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008461 LOCATION_OUTSIDE_ALL_WINDOWS));
8462 ASSERT_TRUE(mDispatcher->waitForIdle());
8463 mFakePolicy->assertNotifyAnrWasNotCalled();
8464}
8465
8466// Since the focused window is paused, tapping on it should not produce any events
8467TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8468 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008469 mDispatcher->onWindowInfosChanged(
8470 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008471
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008472 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008473 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008474 FOCUSED_WINDOW_LOCATION));
8475
8476 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8477 ASSERT_TRUE(mDispatcher->waitForIdle());
8478 // Should not ANR because the window is paused, and touches shouldn't go to it
8479 mFakePolicy->assertNotifyAnrWasNotCalled();
8480
8481 mFocusedWindow->assertNoEvents();
8482 mUnfocusedWindow->assertNoEvents();
8483}
8484
8485/**
8486 * 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 -07008487 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008488 * If a different window becomes focused at this time, the key should go to that window instead.
8489 *
8490 * Warning!!!
8491 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8492 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008493 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008494 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8495 *
8496 * If that value changes, this test should also change.
8497 */
8498TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8499 // Set a long ANR timeout to prevent it from triggering
8500 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008501 mDispatcher->onWindowInfosChanged(
8502 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008503
8504 tapOnUnfocusedWindow();
8505 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8506 ASSERT_TRUE(downSequenceNum);
8507 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8508 ASSERT_TRUE(upSequenceNum);
8509 // Don't finish the events yet, and send a key
8510 // Injection will succeed because we will eventually give up and send the key to the focused
8511 // window even if motions are still being processed.
8512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008513 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008514 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8515 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008517 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008518 // and the key remains pending, waiting for the touch events to be processed.
8519 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8520 // under the hood.
8521 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8522 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008523
8524 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008525 mFocusedWindow->setFocusable(false);
8526 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008527 mDispatcher->onWindowInfosChanged(
8528 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008529 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008530
8531 // Focus events should precede the key events
8532 mUnfocusedWindow->consumeFocusEvent(true);
8533 mFocusedWindow->consumeFocusEvent(false);
8534
8535 // Finish the tap events, which should unblock dispatcher
8536 mUnfocusedWindow->finishEvent(*downSequenceNum);
8537 mUnfocusedWindow->finishEvent(*upSequenceNum);
8538
8539 // Now that all queues are cleared and no backlog in the connections, the key event
8540 // can finally go to the newly focused "mUnfocusedWindow".
8541 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8542 mFocusedWindow->assertNoEvents();
8543 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008544 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008545}
8546
8547// When the touch stream is split across 2 windows, and one of them does not respond,
8548// then ANR should be raised and the touch should be canceled for the unresponsive window.
8549// The other window should not be affected by that.
8550TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8551 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008552 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8553 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8554 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008555 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008556 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008557
8558 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008559 mDispatcher->notifyMotion(
8560 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8561 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008562
8563 const std::chrono::duration timeout =
8564 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008565 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008566
8567 mUnfocusedWindow->consumeMotionDown();
8568 mFocusedWindow->consumeMotionDown();
8569 // Focused window may or may not receive ACTION_MOVE
8570 // But it should definitely receive ACTION_CANCEL due to the ANR
8571 InputEvent* event;
8572 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8573 ASSERT_TRUE(moveOrCancelSequenceNum);
8574 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8575 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008576 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008577 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8578 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8579 mFocusedWindow->consumeMotionCancel();
8580 } else {
8581 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8582 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008583 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008584 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8585 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008586
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008587 mUnfocusedWindow->assertNoEvents();
8588 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008589 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008590}
8591
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008592/**
8593 * If we have no focused window, and a key comes in, we start the ANR timer.
8594 * The focused application should add a focused window before the timer runs out to prevent ANR.
8595 *
8596 * If the user touches another application during this time, the key should be dropped.
8597 * Next, if a new focused window comes in, without toggling the focused application,
8598 * then no ANR should occur.
8599 *
8600 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8601 * but in some cases the policy may not update the focused application.
8602 */
8603TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8604 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8605 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008606 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008607 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8608 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8609 mFocusedWindow->setFocusable(false);
8610
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008611 mDispatcher->onWindowInfosChanged(
8612 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008613 mFocusedWindow->consumeFocusEvent(false);
8614
8615 // Send a key. The ANR timer should start because there is no focused window.
8616 // 'focusedApplication' will get blamed if this timer completes.
8617 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008618 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008619 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8620 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008621 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008623
8624 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8625 // then the injected touches won't cause the focused event to get dropped.
8626 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8627 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8628 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8629 // For this test, it means that the key would get delivered to the window once it becomes
8630 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008631 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008632
8633 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008634 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8635 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8636 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008637
8638 // We do not consume the motion right away, because that would require dispatcher to first
8639 // process (== drop) the key event, and by that time, ANR will be raised.
8640 // Set the focused window first.
8641 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008642 mDispatcher->onWindowInfosChanged(
8643 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008644 setFocusedWindow(mFocusedWindow);
8645 mFocusedWindow->consumeFocusEvent(true);
8646 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8647 // to another application. This could be a bug / behaviour in the policy.
8648
8649 mUnfocusedWindow->consumeMotionDown();
8650
8651 ASSERT_TRUE(mDispatcher->waitForIdle());
8652 // Should not ANR because we actually have a focused window. It was just added too slowly.
8653 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8654}
8655
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008656// These tests ensure we cannot send touch events to a window that's positioned behind a window
8657// that has feature NO_INPUT_CHANNEL.
8658// Layout:
8659// Top (closest to user)
8660// mNoInputWindow (above all windows)
8661// mBottomWindow
8662// Bottom (furthest from user)
8663class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8664 virtual void SetUp() override {
8665 InputDispatcherTest::SetUp();
8666
8667 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008668 mNoInputWindow =
8669 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8670 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008671 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008672 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008673 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8674 // It's perfectly valid for this window to not have an associated input channel
8675
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008676 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8677 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008678 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8679
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008680 mDispatcher->onWindowInfosChanged(
8681 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008682 }
8683
8684protected:
8685 std::shared_ptr<FakeApplicationHandle> mApplication;
8686 sp<FakeWindowHandle> mNoInputWindow;
8687 sp<FakeWindowHandle> mBottomWindow;
8688};
8689
8690TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8691 PointF touchedPoint = {10, 10};
8692
Prabir Pradhan678438e2023-04-13 19:32:51 +00008693 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8694 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8695 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008696
8697 mNoInputWindow->assertNoEvents();
8698 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8699 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8700 // and therefore should prevent mBottomWindow from receiving touches
8701 mBottomWindow->assertNoEvents();
8702}
8703
8704/**
8705 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8706 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8707 */
8708TEST_F(InputDispatcherMultiWindowOcclusionTests,
8709 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008710 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8711 "Window with input channel and NO_INPUT_CHANNEL",
8712 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008713
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008714 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008715 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008716 mDispatcher->onWindowInfosChanged(
8717 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008718
8719 PointF touchedPoint = {10, 10};
8720
Prabir Pradhan678438e2023-04-13 19:32:51 +00008721 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8722 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8723 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008724
8725 mNoInputWindow->assertNoEvents();
8726 mBottomWindow->assertNoEvents();
8727}
8728
Vishnu Nair958da932020-08-21 17:12:37 -07008729class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8730protected:
8731 std::shared_ptr<FakeApplicationHandle> mApp;
8732 sp<FakeWindowHandle> mWindow;
8733 sp<FakeWindowHandle> mMirror;
8734
8735 virtual void SetUp() override {
8736 InputDispatcherTest::SetUp();
8737 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008738 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8739 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8740 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008741 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8742 mWindow->setFocusable(true);
8743 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008744 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008745 }
8746};
8747
8748TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8749 // Request focus on a mirrored window
8750 setFocusedWindow(mMirror);
8751
8752 // window gets focused
8753 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008755 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008756 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8757}
8758
8759// A focused & mirrored window remains focused only if the window and its mirror are both
8760// focusable.
8761TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8762 setFocusedWindow(mMirror);
8763
8764 // window gets focused
8765 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008767 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008768 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008770 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008771 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8772
8773 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008774 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008775
8776 // window loses focus since one of the windows associated with the token in not focusable
8777 mWindow->consumeFocusEvent(false);
8778
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008779 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008780 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008781 mWindow->assertNoEvents();
8782}
8783
8784// A focused & mirrored window remains focused until the window and its mirror both become
8785// invisible.
8786TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8787 setFocusedWindow(mMirror);
8788
8789 // window gets focused
8790 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008792 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008793 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008795 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008796 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8797
8798 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008799 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008800
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008802 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008803 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*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->consumeKeyUp(ADISPLAY_ID_NONE);
8807
8808 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008809 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008810
8811 // window loses focus only after all windows associated with the token become invisible.
8812 mWindow->consumeFocusEvent(false);
8813
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008814 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008815 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008816 mWindow->assertNoEvents();
8817}
8818
8819// A focused & mirrored window remains focused until both windows are removed.
8820TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8821 setFocusedWindow(mMirror);
8822
8823 // window gets focused
8824 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008826 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008827 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008829 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008830 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8831
8832 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008833 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008834
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008836 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008837 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008839 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008840 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8841
8842 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008843 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008844 mWindow->consumeFocusEvent(false);
8845
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008846 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008847 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008848 mWindow->assertNoEvents();
8849}
8850
8851// Focus request can be pending until one window becomes visible.
8852TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8853 // Request focus on an invisible mirror.
8854 mWindow->setVisible(false);
8855 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008856 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008857 setFocusedWindow(mMirror);
8858
8859 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008861 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8862 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008863
8864 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008865 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008866
8867 // window gets focused
8868 mWindow->consumeFocusEvent(true);
8869 // window gets the pending key event
8870 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8871}
Prabir Pradhan99987712020-11-10 18:43:05 -08008872
8873class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8874protected:
8875 std::shared_ptr<FakeApplicationHandle> mApp;
8876 sp<FakeWindowHandle> mWindow;
8877 sp<FakeWindowHandle> mSecondWindow;
8878
8879 void SetUp() override {
8880 InputDispatcherTest::SetUp();
8881 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008882 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008883 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008884 mSecondWindow =
8885 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008886 mSecondWindow->setFocusable(true);
8887
8888 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008889 mDispatcher->onWindowInfosChanged(
8890 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008891
8892 setFocusedWindow(mWindow);
8893 mWindow->consumeFocusEvent(true);
8894 }
8895
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008896 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008897 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008898 }
8899
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008900 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8901 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008902 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008903 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8904 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008905 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008906 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008907 }
8908};
8909
8910TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8911 // Ensure that capture cannot be obtained for unfocused windows.
8912 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8913 mFakePolicy->assertSetPointerCaptureNotCalled();
8914 mSecondWindow->assertNoEvents();
8915
8916 // Ensure that capture can be enabled from the focus window.
8917 requestAndVerifyPointerCapture(mWindow, true);
8918
8919 // Ensure that capture cannot be disabled from a window that does not have capture.
8920 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8921 mFakePolicy->assertSetPointerCaptureNotCalled();
8922
8923 // Ensure that capture can be disabled from the window with capture.
8924 requestAndVerifyPointerCapture(mWindow, false);
8925}
8926
8927TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008928 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008929
8930 setFocusedWindow(mSecondWindow);
8931
8932 // Ensure that the capture disabled event was sent first.
8933 mWindow->consumeCaptureEvent(false);
8934 mWindow->consumeFocusEvent(false);
8935 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008936 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008937
8938 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008939 notifyPointerCaptureChanged({});
8940 notifyPointerCaptureChanged(request);
8941 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008942 mWindow->assertNoEvents();
8943 mSecondWindow->assertNoEvents();
8944 mFakePolicy->assertSetPointerCaptureNotCalled();
8945}
8946
8947TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008948 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008949
8950 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008951 notifyPointerCaptureChanged({});
8952 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008953
8954 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008955 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008956 mWindow->consumeCaptureEvent(false);
8957 mWindow->assertNoEvents();
8958}
8959
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008960TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8961 requestAndVerifyPointerCapture(mWindow, true);
8962
8963 // The first window loses focus.
8964 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008965 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008966 mWindow->consumeCaptureEvent(false);
8967
8968 // Request Pointer Capture from the second window before the notification from InputReader
8969 // arrives.
8970 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008971 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008972
8973 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008974 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008975
8976 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008977 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008978
8979 mSecondWindow->consumeFocusEvent(true);
8980 mSecondWindow->consumeCaptureEvent(true);
8981}
8982
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008983TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8984 // App repeatedly enables and disables capture.
8985 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8986 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8987 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8988 mFakePolicy->assertSetPointerCaptureCalled(false);
8989 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8990 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8991
8992 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8993 // first request is now stale, this should do nothing.
8994 notifyPointerCaptureChanged(firstRequest);
8995 mWindow->assertNoEvents();
8996
8997 // InputReader notifies that the second request was enabled.
8998 notifyPointerCaptureChanged(secondRequest);
8999 mWindow->consumeCaptureEvent(true);
9000}
9001
Prabir Pradhan7092e262022-05-03 16:51:09 +00009002TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9003 requestAndVerifyPointerCapture(mWindow, true);
9004
9005 // App toggles pointer capture off and on.
9006 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9007 mFakePolicy->assertSetPointerCaptureCalled(false);
9008
9009 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9010 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9011
9012 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9013 // preceding "disable" request.
9014 notifyPointerCaptureChanged(enableRequest);
9015
9016 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9017 // any notifications.
9018 mWindow->assertNoEvents();
9019}
9020
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009021/**
9022 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9023 * mouse movements don't affect the previous mouse hovering state.
9024 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9025 * HOVER_MOVE events).
9026 */
9027TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9028 // Mouse hover on the window
9029 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9030 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9031 .build());
9032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9034 .build());
9035
9036 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9037 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9038
9039 // Start pointer capture
9040 requestAndVerifyPointerCapture(mWindow, true);
9041
9042 // Send some relative mouse movements and receive them in the window.
9043 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9045 .build());
9046 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9047 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9048
9049 // Stop pointer capture
9050 requestAndVerifyPointerCapture(mWindow, false);
9051
9052 // Continue hovering on the window
9053 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9055 .build());
9056 mWindow->consumeMotionEvent(
9057 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9058
9059 mWindow->assertNoEvents();
9060}
9061
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009062class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9063protected:
9064 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009065
9066 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9067 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9068
9069 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9070 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9071
9072 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9073 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9074 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9075 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9076 MAXIMUM_OBSCURING_OPACITY);
9077
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009078 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9079 static constexpr gui::Uid APP_B_UID{10002};
9080 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009081
9082 sp<FakeWindowHandle> mTouchWindow;
9083
9084 virtual void SetUp() override {
9085 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009086 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009087 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9088 }
9089
9090 virtual void TearDown() override {
9091 InputDispatcherTest::TearDown();
9092 mTouchWindow.clear();
9093 }
9094
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009095 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009096 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009097 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009098 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009099 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009100 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009101 return window;
9102 }
9103
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009104 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009105 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9106 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009107 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009108 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009109 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009110 return window;
9111 }
9112
9113 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009114 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9115 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9116 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009117 }
9118};
9119
9120TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009121 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009122 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009123 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009124
9125 touch();
9126
9127 mTouchWindow->assertNoEvents();
9128}
9129
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009130TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009131 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9132 const sp<FakeWindowHandle>& w =
9133 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009134 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009135
9136 touch();
9137
9138 mTouchWindow->assertNoEvents();
9139}
9140
9141TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009142 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9143 const sp<FakeWindowHandle>& w =
9144 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009145 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009146
9147 touch();
9148
9149 w->assertNoEvents();
9150}
9151
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009152TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009153 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009154 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009155
9156 touch();
9157
9158 mTouchWindow->consumeAnyMotionDown();
9159}
9160
9161TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009162 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009163 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009164 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009165 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009166
9167 touch({PointF{100, 100}});
9168
9169 mTouchWindow->consumeAnyMotionDown();
9170}
9171
9172TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009173 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009174 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009175 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009176
9177 touch();
9178
9179 mTouchWindow->consumeAnyMotionDown();
9180}
9181
9182TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9183 const sp<FakeWindowHandle>& w =
9184 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009185 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009186
9187 touch();
9188
9189 mTouchWindow->consumeAnyMotionDown();
9190}
9191
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009192TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9193 const sp<FakeWindowHandle>& w =
9194 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009195 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009196
9197 touch();
9198
9199 w->assertNoEvents();
9200}
9201
9202/**
9203 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9204 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9205 * window, the occluding window will still receive ACTION_OUTSIDE event.
9206 */
9207TEST_F(InputDispatcherUntrustedTouchesTest,
9208 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9209 const sp<FakeWindowHandle>& w =
9210 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009211 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009212 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009213
9214 touch();
9215
9216 w->consumeMotionOutside();
9217}
9218
9219TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9220 const sp<FakeWindowHandle>& w =
9221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009222 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009223 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009224
9225 touch();
9226
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009227 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009228}
9229
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009230TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009231 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009232 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9233 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009234 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009235
9236 touch();
9237
9238 mTouchWindow->consumeAnyMotionDown();
9239}
9240
9241TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9242 const sp<FakeWindowHandle>& w =
9243 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9244 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009245 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009246
9247 touch();
9248
9249 mTouchWindow->consumeAnyMotionDown();
9250}
9251
9252TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009253 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009254 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9255 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009256 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009257
9258 touch();
9259
9260 mTouchWindow->assertNoEvents();
9261}
9262
9263TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9264 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9265 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009266 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9267 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009268 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009269 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9270 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009271 mDispatcher->onWindowInfosChanged(
9272 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009273
9274 touch();
9275
9276 mTouchWindow->assertNoEvents();
9277}
9278
9279TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9280 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9281 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009282 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9283 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009284 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009285 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9286 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009287 mDispatcher->onWindowInfosChanged(
9288 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009289
9290 touch();
9291
9292 mTouchWindow->consumeAnyMotionDown();
9293}
9294
9295TEST_F(InputDispatcherUntrustedTouchesTest,
9296 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9297 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009298 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9299 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009300 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009301 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9302 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009303 mDispatcher->onWindowInfosChanged(
9304 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009305
9306 touch();
9307
9308 mTouchWindow->consumeAnyMotionDown();
9309}
9310
9311TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9312 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009313 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9314 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009315 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009316 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9317 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009318 mDispatcher->onWindowInfosChanged(
9319 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009320
9321 touch();
9322
9323 mTouchWindow->assertNoEvents();
9324}
9325
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009326TEST_F(InputDispatcherUntrustedTouchesTest,
9327 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9328 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009329 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9330 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009331 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009332 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9333 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009334 mDispatcher->onWindowInfosChanged(
9335 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009336
9337 touch();
9338
9339 mTouchWindow->assertNoEvents();
9340}
9341
9342TEST_F(InputDispatcherUntrustedTouchesTest,
9343 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9344 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009345 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9346 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009347 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009348 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9349 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009350 mDispatcher->onWindowInfosChanged(
9351 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009352
9353 touch();
9354
9355 mTouchWindow->consumeAnyMotionDown();
9356}
9357
9358TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9359 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009360 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9361 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009362 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009363
9364 touch();
9365
9366 mTouchWindow->consumeAnyMotionDown();
9367}
9368
9369TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9370 const sp<FakeWindowHandle>& w =
9371 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009372 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009373
9374 touch();
9375
9376 mTouchWindow->consumeAnyMotionDown();
9377}
9378
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009379TEST_F(InputDispatcherUntrustedTouchesTest,
9380 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9381 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9382 const sp<FakeWindowHandle>& w =
9383 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009384 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009385
9386 touch();
9387
9388 mTouchWindow->assertNoEvents();
9389}
9390
9391TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9392 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9393 const sp<FakeWindowHandle>& w =
9394 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009395 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009396
9397 touch();
9398
9399 mTouchWindow->consumeAnyMotionDown();
9400}
9401
9402TEST_F(InputDispatcherUntrustedTouchesTest,
9403 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9404 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9405 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009406 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9407 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009408 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009409
9410 touch();
9411
9412 mTouchWindow->consumeAnyMotionDown();
9413}
9414
9415TEST_F(InputDispatcherUntrustedTouchesTest,
9416 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9417 const sp<FakeWindowHandle>& w1 =
9418 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9419 OPACITY_BELOW_THRESHOLD);
9420 const sp<FakeWindowHandle>& w2 =
9421 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9422 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009423 mDispatcher->onWindowInfosChanged(
9424 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009425
9426 touch();
9427
9428 mTouchWindow->assertNoEvents();
9429}
9430
9431/**
9432 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9433 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9434 * (which alone would result in allowing touches) does not affect the blocking behavior.
9435 */
9436TEST_F(InputDispatcherUntrustedTouchesTest,
9437 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9438 const sp<FakeWindowHandle>& wB =
9439 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9440 OPACITY_BELOW_THRESHOLD);
9441 const sp<FakeWindowHandle>& wC =
9442 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9443 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009444 mDispatcher->onWindowInfosChanged(
9445 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009446
9447 touch();
9448
9449 mTouchWindow->assertNoEvents();
9450}
9451
9452/**
9453 * This test is testing that a window from a different UID but with same application token doesn't
9454 * block the touch. Apps can share the application token for close UI collaboration for example.
9455 */
9456TEST_F(InputDispatcherUntrustedTouchesTest,
9457 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9458 const sp<FakeWindowHandle>& w =
9459 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9460 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009461 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009462
9463 touch();
9464
9465 mTouchWindow->consumeAnyMotionDown();
9466}
9467
arthurhungb89ccb02020-12-30 16:19:01 +08009468class InputDispatcherDragTests : public InputDispatcherTest {
9469protected:
9470 std::shared_ptr<FakeApplicationHandle> mApp;
9471 sp<FakeWindowHandle> mWindow;
9472 sp<FakeWindowHandle> mSecondWindow;
9473 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009474 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009475 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9476 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009477
9478 void SetUp() override {
9479 InputDispatcherTest::SetUp();
9480 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009481 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009482 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009483
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009484 mSecondWindow =
9485 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009486 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009487
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009488 mSpyWindow =
9489 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009490 mSpyWindow->setSpy(true);
9491 mSpyWindow->setTrustedOverlay(true);
9492 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9493
arthurhungb89ccb02020-12-30 16:19:01 +08009494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009495 mDispatcher->onWindowInfosChanged(
9496 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9497 {},
9498 0,
9499 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009500 }
9501
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009502 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9503 switch (fromSource) {
9504 case AINPUT_SOURCE_TOUCHSCREEN:
9505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009506 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009507 ADISPLAY_ID_DEFAULT, {50, 50}))
9508 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9509 break;
9510 case AINPUT_SOURCE_STYLUS:
9511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009512 injectMotionEvent(*mDispatcher,
9513 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9514 AINPUT_SOURCE_STYLUS)
9515 .buttonState(
9516 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9517 .pointer(PointerBuilder(0, ToolType::STYLUS)
9518 .x(50)
9519 .y(50))
9520 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009521 break;
9522 case AINPUT_SOURCE_MOUSE:
9523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009524 injectMotionEvent(*mDispatcher,
9525 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9526 AINPUT_SOURCE_MOUSE)
9527 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9528 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9529 ToolType::MOUSE)
9530 .x(50)
9531 .y(50))
9532 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009533 break;
9534 default:
9535 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9536 }
arthurhungb89ccb02020-12-30 16:19:01 +08009537
9538 // Window should receive motion event.
9539 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009540 // Spy window should also receive motion event
9541 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009542 }
9543
9544 // Start performing drag, we will create a drag window and transfer touch to it.
9545 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9546 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009547 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009548 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009549 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009550 }
arthurhungb89ccb02020-12-30 16:19:01 +08009551
9552 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009553 mDragWindow =
9554 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009555 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009556 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9557 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9558 {},
9559 0,
9560 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009561
9562 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009563 bool transferred =
9564 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009565 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009566 if (transferred) {
9567 mWindow->consumeMotionCancel();
9568 mDragWindow->consumeMotionDown();
9569 }
9570 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009571 }
9572};
9573
9574TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009575 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009576
9577 // Move on window.
9578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009579 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009580 ADISPLAY_ID_DEFAULT, {50, 50}))
9581 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9582 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9583 mWindow->consumeDragEvent(false, 50, 50);
9584 mSecondWindow->assertNoEvents();
9585
9586 // Move to another window.
9587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009588 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009589 ADISPLAY_ID_DEFAULT, {150, 50}))
9590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9591 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9592 mWindow->consumeDragEvent(true, 150, 50);
9593 mSecondWindow->consumeDragEvent(false, 50, 50);
9594
9595 // Move back to original window.
9596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009597 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009598 ADISPLAY_ID_DEFAULT, {50, 50}))
9599 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9600 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9601 mWindow->consumeDragEvent(false, 50, 50);
9602 mSecondWindow->consumeDragEvent(true, -50, 50);
9603
9604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009605 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9606 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9608 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9609 mWindow->assertNoEvents();
9610 mSecondWindow->assertNoEvents();
9611}
9612
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009613TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009614 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009615
9616 // No cancel event after drag start
9617 mSpyWindow->assertNoEvents();
9618
9619 const MotionEvent secondFingerDownEvent =
9620 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9621 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009622 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9623 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009624 .build();
9625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009626 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009627 InputEventInjectionSync::WAIT_FOR_RESULT))
9628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9629
9630 // Receives cancel for first pointer after next pointer down
9631 mSpyWindow->consumeMotionCancel();
9632 mSpyWindow->consumeMotionDown();
9633
9634 mSpyWindow->assertNoEvents();
9635}
9636
arthurhungf452d0b2021-01-06 00:19:52 +08009637TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009638 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009639
9640 // Move on window.
9641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009642 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009643 ADISPLAY_ID_DEFAULT, {50, 50}))
9644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9645 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9646 mWindow->consumeDragEvent(false, 50, 50);
9647 mSecondWindow->assertNoEvents();
9648
9649 // Move to another window.
9650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009651 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009652 ADISPLAY_ID_DEFAULT, {150, 50}))
9653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9654 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9655 mWindow->consumeDragEvent(true, 150, 50);
9656 mSecondWindow->consumeDragEvent(false, 50, 50);
9657
9658 // drop to another window.
9659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009660 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009661 {150, 50}))
9662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9663 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009664 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009665 mWindow->assertNoEvents();
9666 mSecondWindow->assertNoEvents();
9667}
9668
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009669TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9670 startDrag();
9671
9672 // No cancel event after drag start
9673 mSpyWindow->assertNoEvents();
9674
9675 const MotionEvent secondFingerDownEvent =
9676 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9677 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9678 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9679 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9680 .build();
9681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9682 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9683 InputEventInjectionSync::WAIT_FOR_RESULT))
9684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9685
9686 // Receives cancel for first pointer after next pointer down
9687 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9688 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9689 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9690
9691 mSpyWindow->assertNoEvents();
9692
9693 // Spy window calls pilfer pointers
9694 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9695 mDragWindow->assertNoEvents();
9696
9697 const MotionEvent firstFingerMoveEvent =
9698 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9699 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9700 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9701 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9702 .build();
9703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9704 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9705 InputEventInjectionSync::WAIT_FOR_RESULT))
9706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9707
9708 // Drag window should still receive the new event
9709 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9710 mDragWindow->assertNoEvents();
9711}
9712
arthurhung6d4bed92021-03-17 11:59:33 +08009713TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009714 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009715
9716 // Move on window and keep button pressed.
9717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009718 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009719 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9720 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009721 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009722 .build()))
9723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9724 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9725 mWindow->consumeDragEvent(false, 50, 50);
9726 mSecondWindow->assertNoEvents();
9727
9728 // Move to another window and release button, expect to drop item.
9729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009730 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009731 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9732 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009733 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009734 .build()))
9735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9736 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9737 mWindow->assertNoEvents();
9738 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009739 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009740
9741 // nothing to the window.
9742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009743 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009744 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9745 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009746 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009747 .build()))
9748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9749 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9750 mWindow->assertNoEvents();
9751 mSecondWindow->assertNoEvents();
9752}
9753
Arthur Hung54745652022-04-20 07:17:41 +00009754TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009755 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009756
9757 // Set second window invisible.
9758 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009759 mDispatcher->onWindowInfosChanged(
9760 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009761
9762 // Move on window.
9763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009764 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009765 ADISPLAY_ID_DEFAULT, {50, 50}))
9766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9767 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9768 mWindow->consumeDragEvent(false, 50, 50);
9769 mSecondWindow->assertNoEvents();
9770
9771 // Move to another window.
9772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009773 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009774 ADISPLAY_ID_DEFAULT, {150, 50}))
9775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9776 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9777 mWindow->consumeDragEvent(true, 150, 50);
9778 mSecondWindow->assertNoEvents();
9779
9780 // drop to another window.
9781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009782 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009783 {150, 50}))
9784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9785 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009786 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009787 mWindow->assertNoEvents();
9788 mSecondWindow->assertNoEvents();
9789}
9790
Arthur Hung54745652022-04-20 07:17:41 +00009791TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009792 // Ensure window could track pointerIds if it didn't support split touch.
9793 mWindow->setPreventSplitting(true);
9794
Arthur Hung54745652022-04-20 07:17:41 +00009795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009796 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009797 {50, 50}))
9798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9799 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9800
9801 const MotionEvent secondFingerDownEvent =
9802 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9803 .displayId(ADISPLAY_ID_DEFAULT)
9804 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009805 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9806 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009807 .build();
9808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009809 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009810 InputEventInjectionSync::WAIT_FOR_RESULT))
9811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009812 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009813
9814 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009815 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009816}
9817
9818TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9819 // First down on second window.
9820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009821 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009822 {150, 50}))
9823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9824
9825 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9826
9827 // Second down on first window.
9828 const MotionEvent secondFingerDownEvent =
9829 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9830 .displayId(ADISPLAY_ID_DEFAULT)
9831 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009832 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9833 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009834 .build();
9835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009836 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009837 InputEventInjectionSync::WAIT_FOR_RESULT))
9838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9839 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9840
9841 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009842 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009843
9844 // Move on window.
9845 const MotionEvent secondFingerMoveEvent =
9846 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9847 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009848 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9849 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009850 .build();
9851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009852 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009853 InputEventInjectionSync::WAIT_FOR_RESULT));
9854 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9855 mWindow->consumeDragEvent(false, 50, 50);
9856 mSecondWindow->consumeMotionMove();
9857
9858 // Release the drag pointer should perform drop.
9859 const MotionEvent secondFingerUpEvent =
9860 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9861 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009862 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9863 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009864 .build();
9865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009866 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009867 InputEventInjectionSync::WAIT_FOR_RESULT));
9868 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009869 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009870 mWindow->assertNoEvents();
9871 mSecondWindow->consumeMotionMove();
9872}
9873
Arthur Hung3915c1f2022-05-31 07:17:17 +00009874TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009875 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009876
9877 // Update window of second display.
9878 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009879 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009880 mDispatcher->onWindowInfosChanged(
9881 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9882 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9883 {},
9884 0,
9885 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009886
9887 // Let second display has a touch state.
9888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009889 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009890 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9891 AINPUT_SOURCE_TOUCHSCREEN)
9892 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009893 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009894 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009895 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009896 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009897 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009898 mDispatcher->onWindowInfosChanged(
9899 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9900 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9901 {},
9902 0,
9903 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009904
9905 // Move on window.
9906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009907 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009908 ADISPLAY_ID_DEFAULT, {50, 50}))
9909 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9910 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9911 mWindow->consumeDragEvent(false, 50, 50);
9912 mSecondWindow->assertNoEvents();
9913
9914 // Move to another window.
9915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009916 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009917 ADISPLAY_ID_DEFAULT, {150, 50}))
9918 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9919 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9920 mWindow->consumeDragEvent(true, 150, 50);
9921 mSecondWindow->consumeDragEvent(false, 50, 50);
9922
9923 // drop to another window.
9924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009925 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009926 {150, 50}))
9927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9928 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009929 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009930 mWindow->assertNoEvents();
9931 mSecondWindow->assertNoEvents();
9932}
9933
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009934TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9935 startDrag(true, AINPUT_SOURCE_MOUSE);
9936 // Move on window.
9937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009938 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009939 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9940 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009941 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009942 .x(50)
9943 .y(50))
9944 .build()))
9945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9946 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9947 mWindow->consumeDragEvent(false, 50, 50);
9948 mSecondWindow->assertNoEvents();
9949
9950 // Move to another window.
9951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009952 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009953 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9954 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009955 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009956 .x(150)
9957 .y(50))
9958 .build()))
9959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9960 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9961 mWindow->consumeDragEvent(true, 150, 50);
9962 mSecondWindow->consumeDragEvent(false, 50, 50);
9963
9964 // drop to another window.
9965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009966 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009967 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9968 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009969 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009970 .x(150)
9971 .y(50))
9972 .build()))
9973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9974 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009975 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009976 mWindow->assertNoEvents();
9977 mSecondWindow->assertNoEvents();
9978}
9979
Linnan Li5af92f92023-07-14 14:36:22 +08009980/**
9981 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9982 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9983 */
9984TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9985 // Down on second window
9986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9987 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9988 {150, 50}))
9989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9990
9991 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9992 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9993
9994 // Down on first window
9995 const MotionEvent secondFingerDownEvent =
9996 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9997 .displayId(ADISPLAY_ID_DEFAULT)
9998 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9999 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10000 .build();
10001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10002 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10003 InputEventInjectionSync::WAIT_FOR_RESULT))
10004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10005 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10006 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10007 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10008
10009 // Start drag on first window
10010 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10011
10012 // Trigger cancel
10013 mDispatcher->cancelCurrentTouch();
10014 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10015 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10016 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10017
10018 ASSERT_TRUE(mDispatcher->waitForIdle());
10019 // The D&D finished with nullptr
10020 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10021
10022 // Remove drag window
10023 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10024
10025 // Inject a simple gesture, ensure dispatcher not crashed
10026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10027 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10028 PointF{50, 50}))
10029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10030 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10031
10032 const MotionEvent moveEvent =
10033 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10034 .displayId(ADISPLAY_ID_DEFAULT)
10035 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10036 .build();
10037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10038 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10039 InputEventInjectionSync::WAIT_FOR_RESULT))
10040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10041 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10042
10043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10044 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10045 {50, 50}))
10046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10047 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10048}
10049
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010050TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10051 // Start hovering over the window.
10052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10053 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10054 ADISPLAY_ID_DEFAULT, {50, 50}));
10055
10056 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10057 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10058
10059 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10060 << "Drag and drop should not work with a hovering pointer";
10061}
10062
Vishnu Nair062a8672021-09-03 16:07:44 -070010063class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10064
10065TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010067 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10068 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010069 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010070 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10071 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010072 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010073 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010074 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010075
10076 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010077 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010078 window->assertNoEvents();
10079
Prabir Pradhan678438e2023-04-13 19:32:51 +000010080 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10081 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010082 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10083 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010084 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010085 window->assertNoEvents();
10086
10087 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010088 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010089 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010090
Prabir Pradhan678438e2023-04-13 19:32:51 +000010091 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010092 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10093
Prabir Pradhan678438e2023-04-13 19:32:51 +000010094 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10095 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010096 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10097 window->assertNoEvents();
10098}
10099
10100TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10101 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10102 std::make_shared<FakeApplicationHandle>();
10103 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010104 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10105 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010106 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010107 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010108 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010110 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10111 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010112 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010113 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010114 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10115 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010116 mDispatcher->onWindowInfosChanged(
10117 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010118 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010119 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010120
10121 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010122 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010123 window->assertNoEvents();
10124
Prabir Pradhan678438e2023-04-13 19:32:51 +000010125 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10126 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10128 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010129 window->assertNoEvents();
10130
10131 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010132 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010133 mDispatcher->onWindowInfosChanged(
10134 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010135
Prabir Pradhan678438e2023-04-13 19:32:51 +000010136 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010137 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10138
Prabir Pradhan678438e2023-04-13 19:32:51 +000010139 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10140 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010141 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10142 window->assertNoEvents();
10143}
10144
10145TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10146 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10147 std::make_shared<FakeApplicationHandle>();
10148 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010149 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10150 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010151 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010152 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010153 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010155 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10156 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010157 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010158 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010159 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10160 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010161 mDispatcher->onWindowInfosChanged(
10162 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010163 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010164 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010165
10166 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010167 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010168 window->assertNoEvents();
10169
Prabir Pradhan678438e2023-04-13 19:32:51 +000010170 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10171 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010172 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10173 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010174 window->assertNoEvents();
10175
10176 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010177 mDispatcher->onWindowInfosChanged(
10178 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010179
Prabir Pradhan678438e2023-04-13 19:32:51 +000010180 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010181 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10182
Prabir Pradhan678438e2023-04-13 19:32:51 +000010183 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10184 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010185 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10186 window->assertNoEvents();
10187}
10188
Antonio Kantekf16f2832021-09-28 04:39:20 +000010189class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10190protected:
10191 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010192 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010193 sp<FakeWindowHandle> mWindow;
10194 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010195 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010196
10197 void SetUp() override {
10198 InputDispatcherTest::SetUp();
10199
10200 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010201 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010202 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010203 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010204 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010205 mSecondWindow =
10206 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010207 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010208 mThirdWindow =
10209 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10210 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10211 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010212
10213 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010214 mDispatcher->onWindowInfosChanged(
10215 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10216 {},
10217 0,
10218 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010219 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010220 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010221
Antonio Kantek15beb512022-06-13 22:35:41 +000010222 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010223 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010224 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010225 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10226 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010227 mThirdWindow->assertNoEvents();
10228 }
10229
10230 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10231 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010232 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010233 SECOND_DISPLAY_ID)) {
10234 mWindow->assertNoEvents();
10235 mSecondWindow->assertNoEvents();
10236 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010237 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010238 }
10239
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010240 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010241 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010242 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10243 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010244 mWindow->consumeTouchModeEvent(inTouchMode);
10245 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010246 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010247 }
10248};
10249
Antonio Kantek26defcf2022-02-08 01:12:27 +000010250TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010251 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010252 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10253 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010254 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010255}
10256
Antonio Kantek26defcf2022-02-08 01:12:27 +000010257TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10258 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010259 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010260 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010261 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010262 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010263 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010264 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010265 mWindow->assertNoEvents();
10266 mSecondWindow->assertNoEvents();
10267}
10268
10269TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10270 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010271 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010272 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010273 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010274 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010275 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010276}
10277
Antonio Kantekf16f2832021-09-28 04:39:20 +000010278TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010279 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010280 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10281 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010282 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010283 mWindow->assertNoEvents();
10284 mSecondWindow->assertNoEvents();
10285}
10286
Antonio Kantek15beb512022-06-13 22:35:41 +000010287TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10288 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10289 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10290 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010291 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010292 mWindow->assertNoEvents();
10293 mSecondWindow->assertNoEvents();
10294 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10295}
10296
Antonio Kantek48710e42022-03-24 14:19:30 -070010297TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10298 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10300 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010301 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10302 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10303
10304 // Then remove focus.
10305 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010306 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010307
10308 // Assert that caller can switch touch mode by owning one of the last interacted window.
10309 const WindowInfo& windowInfo = *mWindow->getInfo();
10310 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10311 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010312 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010313}
10314
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010315class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10316public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010317 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010318 std::shared_ptr<FakeApplicationHandle> application =
10319 std::make_shared<FakeApplicationHandle>();
10320 std::string name = "Fake Spy ";
10321 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010322 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10323 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010324 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010325 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010326 return spy;
10327 }
10328
10329 sp<FakeWindowHandle> createForeground() {
10330 std::shared_ptr<FakeApplicationHandle> application =
10331 std::make_shared<FakeApplicationHandle>();
10332 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010333 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10334 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010335 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010336 return window;
10337 }
10338
10339private:
10340 int mSpyCount{0};
10341};
10342
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010343using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010344/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010345 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10346 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010347TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010348 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010349 ScopedSilentDeath _silentDeath;
10350
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010351 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010352 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010353 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010354 ".* not a trusted overlay");
10355}
10356
10357/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010358 * Input injection into a display with a spy window but no foreground windows should succeed.
10359 */
10360TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010361 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010362 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010363
10364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010365 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010366 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10367 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10368}
10369
10370/**
10371 * Verify the order in which different input windows receive events. The touched foreground window
10372 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10373 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10374 * receive events before ones belows it.
10375 *
10376 * Here, we set up a scenario with four windows in the following Z order from the top:
10377 * spy1, spy2, window, spy3.
10378 * We then inject an event and verify that the foreground "window" receives it first, followed by
10379 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10380 * window.
10381 */
10382TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10383 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010384 auto spy1 = createSpy();
10385 auto spy2 = createSpy();
10386 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010387 mDispatcher->onWindowInfosChanged(
10388 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010389 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10390 const size_t numChannels = channels.size();
10391
Michael Wright8e9a8562022-02-09 13:44:29 +000010392 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010393 if (!epollFd.ok()) {
10394 FAIL() << "Failed to create epoll fd";
10395 }
10396
10397 for (size_t i = 0; i < numChannels; i++) {
10398 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10399 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10400 FAIL() << "Failed to add fd to epoll";
10401 }
10402 }
10403
10404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010405 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010406 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10407
10408 std::vector<size_t> eventOrder;
10409 std::vector<struct epoll_event> events(numChannels);
10410 for (;;) {
10411 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10412 (100ms).count());
10413 if (nFds < 0) {
10414 FAIL() << "Failed to call epoll_wait";
10415 }
10416 if (nFds == 0) {
10417 break; // epoll_wait timed out
10418 }
10419 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010420 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010421 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010422 channels[i]->consumeMotionDown();
10423 }
10424 }
10425
10426 // Verify the order in which the events were received.
10427 EXPECT_EQ(3u, eventOrder.size());
10428 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10429 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10430 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10431}
10432
10433/**
10434 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10435 */
10436TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10437 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010438 auto spy = createSpy();
10439 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010440 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010441
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 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10446 spy->assertNoEvents();
10447}
10448
10449/**
10450 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10451 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10452 * to the window.
10453 */
10454TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10455 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010456 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010457 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010458 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010459
10460 // Inject an event outside the spy window's touchable region.
10461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010462 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010463 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10464 window->consumeMotionDown();
10465 spy->assertNoEvents();
10466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010467 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10469 window->consumeMotionUp();
10470 spy->assertNoEvents();
10471
10472 // Inject an event inside the spy window's touchable region.
10473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010474 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010475 {5, 10}))
10476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10477 window->consumeMotionDown();
10478 spy->consumeMotionDown();
10479}
10480
10481/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010482 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010483 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010484 */
10485TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10486 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010487 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010488 auto spy = createSpy();
10489 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010490 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010491 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010492 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010493
10494 // Inject an event outside the spy window's frame and touchable region.
10495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010496 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010497 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010498 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10499 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010500 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010501}
10502
10503/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010504 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10505 * pointers that are down within its bounds.
10506 */
10507TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10508 auto windowLeft = createForeground();
10509 windowLeft->setFrame({0, 0, 100, 200});
10510 auto windowRight = createForeground();
10511 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010512 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010513 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010514 mDispatcher->onWindowInfosChanged(
10515 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010516
10517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010518 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010519 {50, 50}))
10520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10521 windowLeft->consumeMotionDown();
10522 spy->consumeMotionDown();
10523
10524 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010525 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010526 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010527 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10528 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010529 .build();
10530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010531 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010532 InputEventInjectionSync::WAIT_FOR_RESULT))
10533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10534 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010535 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010536}
10537
10538/**
10539 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10540 * the spy should receive the second pointer with ACTION_DOWN.
10541 */
10542TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10543 auto window = createForeground();
10544 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010545 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010546 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010547 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010548
10549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010550 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010551 {50, 50}))
10552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10553 window->consumeMotionDown();
10554 spyRight->assertNoEvents();
10555
10556 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010557 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010558 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010559 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10560 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010561 .build();
10562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010563 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010564 InputEventInjectionSync::WAIT_FOR_RESULT))
10565 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010566 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010567 spyRight->consumeMotionDown();
10568}
10569
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010570/**
10571 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10572 * windows should be allowed to control split touch.
10573 */
10574TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010575 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010576 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010577 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010578 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010579
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010580 auto window = createForeground();
10581 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010582
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010583 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010584
10585 // First finger down, no window touched.
10586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010587 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010588 {100, 200}))
10589 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10590 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10591 window->assertNoEvents();
10592
10593 // Second finger down on window, the window should receive touch down.
10594 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010595 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010596 .displayId(ADISPLAY_ID_DEFAULT)
10597 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010598 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10599 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010600 .build();
10601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010602 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010603 InputEventInjectionSync::WAIT_FOR_RESULT))
10604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10605
10606 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010607 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010608}
10609
10610/**
10611 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10612 * do not receive key events.
10613 */
10614TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010615 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010616 spy->setFocusable(false);
10617
10618 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010619 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010620 setFocusedWindow(window);
10621 window->consumeFocusEvent(true);
10622
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010624 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10625 window->consumeKeyDown(ADISPLAY_ID_NONE);
10626
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010628 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10629 window->consumeKeyUp(ADISPLAY_ID_NONE);
10630
10631 spy->assertNoEvents();
10632}
10633
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010634using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10635
10636/**
10637 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10638 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10639 */
10640TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10641 auto window = createForeground();
10642 auto spy1 = createSpy();
10643 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010644 mDispatcher->onWindowInfosChanged(
10645 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010646
10647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010648 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10650 window->consumeMotionDown();
10651 spy1->consumeMotionDown();
10652 spy2->consumeMotionDown();
10653
10654 // Pilfer pointers from the second spy window.
10655 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10656 spy2->assertNoEvents();
10657 spy1->consumeMotionCancel();
10658 window->consumeMotionCancel();
10659
10660 // The rest of the gesture should only be sent to the second spy window.
10661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010662 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010663 ADISPLAY_ID_DEFAULT))
10664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10665 spy2->consumeMotionMove();
10666 spy1->assertNoEvents();
10667 window->assertNoEvents();
10668}
10669
10670/**
10671 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10672 * in the middle of the gesture.
10673 */
10674TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10675 auto window = createForeground();
10676 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010677 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010678
10679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010680 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10683 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10684
10685 window->releaseChannel();
10686
10687 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10688
10689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010690 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10692 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10693}
10694
10695/**
10696 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10697 * the spy, but not to any other windows.
10698 */
10699TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10700 auto spy = createSpy();
10701 auto window = createForeground();
10702
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010703 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010704
10705 // First finger down on the window and the spy.
10706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010707 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010708 {100, 200}))
10709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10710 spy->consumeMotionDown();
10711 window->consumeMotionDown();
10712
10713 // Spy window pilfers the pointers.
10714 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10715 window->consumeMotionCancel();
10716
10717 // Second finger down on the window and spy, but the window should not receive the pointer down.
10718 const MotionEvent secondFingerDownEvent =
10719 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10720 .displayId(ADISPLAY_ID_DEFAULT)
10721 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010722 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10723 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010724 .build();
10725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010726 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010727 InputEventInjectionSync::WAIT_FOR_RESULT))
10728 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10729
Harry Cutts33476232023-01-30 19:57:29 +000010730 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010731
10732 // Third finger goes down outside all windows, so injection should fail.
10733 const MotionEvent thirdFingerDownEvent =
10734 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10735 .displayId(ADISPLAY_ID_DEFAULT)
10736 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010737 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10738 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10739 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010740 .build();
10741 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010742 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010743 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010744 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010745
10746 spy->assertNoEvents();
10747 window->assertNoEvents();
10748}
10749
10750/**
10751 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10752 */
10753TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10754 auto spy = createSpy();
10755 spy->setFrame(Rect(0, 0, 100, 100));
10756 auto window = createForeground();
10757 window->setFrame(Rect(0, 0, 200, 200));
10758
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010759 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010760
10761 // First finger down on the window only
10762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010763 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010764 {150, 150}))
10765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10766 window->consumeMotionDown();
10767
10768 // Second finger down on the spy and window
10769 const MotionEvent secondFingerDownEvent =
10770 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10771 .displayId(ADISPLAY_ID_DEFAULT)
10772 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010773 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10774 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010775 .build();
10776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010777 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010778 InputEventInjectionSync::WAIT_FOR_RESULT))
10779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10780 spy->consumeMotionDown();
10781 window->consumeMotionPointerDown(1);
10782
10783 // Third finger down on the spy and window
10784 const MotionEvent thirdFingerDownEvent =
10785 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10786 .displayId(ADISPLAY_ID_DEFAULT)
10787 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010788 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10789 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10790 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010791 .build();
10792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010793 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010794 InputEventInjectionSync::WAIT_FOR_RESULT))
10795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10796 spy->consumeMotionPointerDown(1);
10797 window->consumeMotionPointerDown(2);
10798
10799 // Spy window pilfers the pointers.
10800 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010801 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10802 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010803
10804 spy->assertNoEvents();
10805 window->assertNoEvents();
10806}
10807
10808/**
10809 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10810 * other windows should be canceled. If this results in the cancellation of all pointers for some
10811 * window, then that window should receive ACTION_CANCEL.
10812 */
10813TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10814 auto spy = createSpy();
10815 spy->setFrame(Rect(0, 0, 100, 100));
10816 auto window = createForeground();
10817 window->setFrame(Rect(0, 0, 200, 200));
10818
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010819 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010820
10821 // First finger down on both spy and window
10822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010823 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010824 {10, 10}))
10825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10826 window->consumeMotionDown();
10827 spy->consumeMotionDown();
10828
10829 // Second finger down on the spy and window
10830 const MotionEvent secondFingerDownEvent =
10831 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10832 .displayId(ADISPLAY_ID_DEFAULT)
10833 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010834 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10835 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010836 .build();
10837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010838 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010839 InputEventInjectionSync::WAIT_FOR_RESULT))
10840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10841 spy->consumeMotionPointerDown(1);
10842 window->consumeMotionPointerDown(1);
10843
10844 // Spy window pilfers the pointers.
10845 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10846 window->consumeMotionCancel();
10847
10848 spy->assertNoEvents();
10849 window->assertNoEvents();
10850}
10851
10852/**
10853 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10854 * be sent to other windows
10855 */
10856TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10857 auto spy = createSpy();
10858 spy->setFrame(Rect(0, 0, 100, 100));
10859 auto window = createForeground();
10860 window->setFrame(Rect(0, 0, 200, 200));
10861
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010862 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010863
10864 // First finger down on both window and spy
10865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010866 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010867 {10, 10}))
10868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10869 window->consumeMotionDown();
10870 spy->consumeMotionDown();
10871
10872 // Spy window pilfers the pointers.
10873 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10874 window->consumeMotionCancel();
10875
10876 // Second finger down on the window only
10877 const MotionEvent secondFingerDownEvent =
10878 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10879 .displayId(ADISPLAY_ID_DEFAULT)
10880 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010881 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10882 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010883 .build();
10884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010885 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010886 InputEventInjectionSync::WAIT_FOR_RESULT))
10887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10888 window->consumeMotionDown();
10889 window->assertNoEvents();
10890
10891 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10892 spy->consumeMotionMove();
10893 spy->assertNoEvents();
10894}
10895
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010896/**
10897 * A window on the left and a window on the right. Also, a spy window that's above all of the
10898 * windows, and spanning both left and right windows.
10899 * Send simultaneous motion streams from two different devices, one to the left window, and another
10900 * to the right window.
10901 * Pilfer from spy window.
10902 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10903 */
10904TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10905 sp<FakeWindowHandle> spy = createSpy();
10906 spy->setFrame(Rect(0, 0, 200, 200));
10907 sp<FakeWindowHandle> leftWindow = createForeground();
10908 leftWindow->setFrame(Rect(0, 0, 100, 100));
10909
10910 sp<FakeWindowHandle> rightWindow = createForeground();
10911 rightWindow->setFrame(Rect(100, 0, 200, 100));
10912
10913 constexpr int32_t stylusDeviceId = 1;
10914 constexpr int32_t touchDeviceId = 2;
10915
10916 mDispatcher->onWindowInfosChanged(
10917 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10918
10919 // Stylus down on left window and spy
10920 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10921 .deviceId(stylusDeviceId)
10922 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10923 .build());
10924 leftWindow->consumeMotionEvent(
10925 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10926 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10927
10928 // Finger down on right window and spy - but spy already has stylus
10929 mDispatcher->notifyMotion(
10930 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10931 .deviceId(touchDeviceId)
10932 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10933 .build());
10934 rightWindow->consumeMotionEvent(
10935 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010936 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010937
10938 // Act: pilfer from spy. Spy is currently receiving touch events.
10939 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010940 leftWindow->consumeMotionEvent(
10941 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010942 rightWindow->consumeMotionEvent(
10943 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10944
10945 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10946 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10947 .deviceId(stylusDeviceId)
10948 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10949 .build());
10950 mDispatcher->notifyMotion(
10951 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10952 .deviceId(touchDeviceId)
10953 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10954 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010955 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010956
10957 spy->assertNoEvents();
10958 leftWindow->assertNoEvents();
10959 rightWindow->assertNoEvents();
10960}
10961
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010962TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
10963 auto window = createForeground();
10964 auto spy = createSpy();
10965 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
10966
10967 mDispatcher->notifyMotion(
10968 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10969 .deviceId(1)
10970 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
10971 .build());
10972 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
10973 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
10974
10975 // Pilfer pointers from the spy window should fail.
10976 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
10977 spy->assertNoEvents();
10978 window->assertNoEvents();
10979}
10980
Prabir Pradhand65552b2021-10-07 11:23:50 -070010981class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10982public:
10983 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10984 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10985 std::make_shared<FakeApplicationHandle>();
10986 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010987 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10988 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010989 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010990 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010991 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010992 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010993 overlay->setTrustedOverlay(true);
10994
10995 std::shared_ptr<FakeApplicationHandle> application =
10996 std::make_shared<FakeApplicationHandle>();
10997 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010998 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10999 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011000 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011001 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011002
11003 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011004 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011005 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011006 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011007 return {std::move(overlay), std::move(window)};
11008 }
11009
11010 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011011 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011012 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011013 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011014 }
11015
11016 void sendStylusEvent(int32_t action) {
11017 NotifyMotionArgs motionArgs =
11018 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11019 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011020 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011021 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011022 }
11023};
11024
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011025using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11026
11027TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011028 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011029 ScopedSilentDeath _silentDeath;
11030
Prabir Pradhand65552b2021-10-07 11:23:50 -070011031 auto [overlay, window] = setupStylusOverlayScenario();
11032 overlay->setTrustedOverlay(false);
11033 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011034 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11035 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011036 ".* not a trusted overlay");
11037}
11038
11039TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11040 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011041 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011042
11043 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11044 overlay->consumeMotionDown();
11045 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11046 overlay->consumeMotionUp();
11047
11048 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11049 window->consumeMotionDown();
11050 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11051 window->consumeMotionUp();
11052
11053 overlay->assertNoEvents();
11054 window->assertNoEvents();
11055}
11056
11057TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11058 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011059 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011060 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011061
11062 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11063 overlay->consumeMotionDown();
11064 window->consumeMotionDown();
11065 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11066 overlay->consumeMotionUp();
11067 window->consumeMotionUp();
11068
11069 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11070 window->consumeMotionDown();
11071 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11072 window->consumeMotionUp();
11073
11074 overlay->assertNoEvents();
11075 window->assertNoEvents();
11076}
11077
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011078/**
11079 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11080 * The scenario is as follows:
11081 * - The stylus interceptor overlay is configured as a spy window.
11082 * - The stylus interceptor spy receives the start of a new stylus gesture.
11083 * - It pilfers pointers and then configures itself to no longer be a spy.
11084 * - The stylus interceptor continues to receive the rest of the gesture.
11085 */
11086TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11087 auto [overlay, window] = setupStylusOverlayScenario();
11088 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011089 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011090
11091 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11092 overlay->consumeMotionDown();
11093 window->consumeMotionDown();
11094
11095 // The interceptor pilfers the pointers.
11096 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11097 window->consumeMotionCancel();
11098
11099 // The interceptor configures itself so that it is no longer a spy.
11100 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011101 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011102
11103 // It continues to receive the rest of the stylus gesture.
11104 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11105 overlay->consumeMotionMove();
11106 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11107 overlay->consumeMotionUp();
11108
11109 window->assertNoEvents();
11110}
11111
Prabir Pradhan5735a322022-04-11 17:23:34 +000011112struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011113 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011114 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011115 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11116 std::unique_ptr<InputDispatcher>& mDispatcher;
11117
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011118 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011119 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11120
11121 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011122 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011123 ADISPLAY_ID_DEFAULT, {100, 200},
11124 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11125 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11126 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11127 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11128 }
11129
11130 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011131 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011132 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011133 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011134 mPolicyFlags);
11135 }
11136
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011137 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011138 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11139 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011140 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11141 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011142 window->setOwnerInfo(mPid, mUid);
11143 return window;
11144 }
11145};
11146
11147using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11148
11149TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011150 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011151 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011152 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011153
11154 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11155 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11156 window->consumeMotionDown();
11157
11158 setFocusedWindow(window);
11159 window->consumeFocusEvent(true);
11160
11161 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11162 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11163 window->consumeKeyDown(ADISPLAY_ID_NONE);
11164}
11165
11166TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011167 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011168 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011169 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011170
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011171 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011172 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11173 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11174
11175 setFocusedWindow(window);
11176 window->consumeFocusEvent(true);
11177
11178 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11179 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11180 window->assertNoEvents();
11181}
11182
11183TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011184 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011185 auto window = owner.createWindow("Owned window");
11186 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011187 spy->setSpy(true);
11188 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011189 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011190
11191 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11192 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11193 spy->consumeMotionDown();
11194 window->consumeMotionDown();
11195}
11196
11197TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011198 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011199 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011200
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011201 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011202 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011203 randosSpy->setSpy(true);
11204 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011205 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011206
11207 // The event is targeted at owner's window, so injection should succeed, but the spy should
11208 // not receive the event.
11209 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11210 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11211 randosSpy->assertNoEvents();
11212 window->consumeMotionDown();
11213}
11214
11215TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011216 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011217 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011218
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011219 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011220 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011221 randosSpy->setSpy(true);
11222 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011223 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011224
11225 // A user that has injection permission can inject into any window.
11226 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011227 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011228 ADISPLAY_ID_DEFAULT));
11229 randosSpy->consumeMotionDown();
11230 window->consumeMotionDown();
11231
11232 setFocusedWindow(randosSpy);
11233 randosSpy->consumeFocusEvent(true);
11234
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011235 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011236 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11237 window->assertNoEvents();
11238}
11239
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011240TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011241 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011242 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011243
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011244 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011245 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011246 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11247 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011248 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011249
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011250 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011251 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11252 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11253 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011254 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011255}
11256
Garfield Tane84e6f92019-08-29 17:28:41 -070011257} // namespace android::inputdispatcher