blob: 561a81b7281699ea779f2bd7fc5bcbed6d059eb7 [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"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000019#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Cody Heiner166a5af2023-07-07 12:25:00 -070021#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070022#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080023#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080024#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070025#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070026#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000027#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080028#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080029#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070031#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080032#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080033#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034
Garfield Tan1c7bc862020-01-28 13:24:04 -080035#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080036#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070037#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080038#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080039#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040
Garfield Tan1c7bc862020-01-28 13:24:04 -080041using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050042using android::gui::FocusRequest;
43using android::gui::TouchOcclusionMode;
44using android::gui::WindowInfo;
45using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080046using android::os::InputEventInjectionResult;
47using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080048
Garfield Tane84e6f92019-08-29 17:28:41 -070049namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080050
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080052using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070053
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070054namespace {
55
Michael Wrightd02c5b62014-02-10 15:10:22 -080056// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000057static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
59// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000060static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080061static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080062
Jeff Brownf086ddb2014-02-11 14:28:48 -080063// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000064static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
65static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080066
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000067// Ensure common actions are interchangeable between keys and motions for convenience.
68static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
69static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080070static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
71static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
72static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
73static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070074static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070076static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080077static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080078static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080079/**
80 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
81 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
82 * index 0) is the new pointer going down. The same pointer could have been placed at a different
83 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
84 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
85 * pointer id=0 leaves but the pointer id=1 remains.
86 */
87static constexpr int32_t POINTER_0_DOWN =
88 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080089static constexpr int32_t POINTER_1_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000091static constexpr int32_t POINTER_2_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000093static constexpr int32_t POINTER_3_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000095static constexpr int32_t POINTER_0_UP =
96 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080097static constexpr int32_t POINTER_1_UP =
98 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000099static constexpr int32_t POINTER_2_UP =
100 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800101
Antonio Kantek15beb512022-06-13 22:35:41 +0000102// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000103static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000104static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000105
Antonio Kantek15beb512022-06-13 22:35:41 +0000106// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000107static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000108static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000109
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000110// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000111static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000112
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800113static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
114
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700115/**
116 * If we expect to receive the event, the timeout can be made very long. When the test are running
117 * correctly, we will actually never wait until the end of the timeout because the wait will end
118 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
119 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
120 * developer can see the failure quickly (on human scale).
121 */
122static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
123/**
124 * When no event is expected, we can have a very short timeout. A large value here would slow down
125 * the tests. In the unlikely event of system being too slow, the event may still be present but the
126 * timeout would complete before it is consumed. This would result in test flakiness. If this
127 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
128 * would get noticed and addressed quickly.
129 */
130static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
131
Arthur Hungc539dbb2022-12-08 07:45:36 +0000132static constexpr int expectedWallpaperFlags =
133 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
134
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800135using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
136
Gang Wang342c9272020-01-13 13:15:04 -0500137/**
138 * Return a DOWN key event with KEYCODE_A.
139 */
140static KeyEvent getTestKeyEvent() {
141 KeyEvent event;
142
Garfield Tanfbe732e2020-01-24 11:26:14 -0800143 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
144 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
145 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500146 return event;
147}
148
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149// --- FakeInputDispatcherPolicy ---
150
151class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000152 struct AnrResult {
153 sp<IBinder> token{};
154 gui::Pid pid{gui::Pid::INVALID};
155 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800156
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000158 FakeInputDispatcherPolicy() = default;
159 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800160
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800161 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700162 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700163 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700164 EXPECT_EQ(event.getDisplayId(), args.displayId);
165
166 const auto& keyEvent = static_cast<const KeyEvent&>(event);
167 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
168 EXPECT_EQ(keyEvent.getAction(), args.action);
169 });
Jackal Guof9696682018-10-05 12:23:23 +0800170 }
171
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700172 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
173 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700174 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 EXPECT_EQ(event.getDisplayId(), args.displayId);
176
177 const auto& motionEvent = static_cast<const MotionEvent&>(event);
178 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
179 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000180 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
181 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
182 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
183 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700184 });
Jackal Guof9696682018-10-05 12:23:23 +0800185 }
186
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700187 void assertFilterInputEventWasNotCalled() {
188 std::scoped_lock lock(mLock);
189 ASSERT_EQ(nullptr, mFilteredEvent);
190 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800192 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700193 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 ASSERT_TRUE(mConfigurationChangedTime)
195 << "Timed out waiting for configuration changed call";
196 ASSERT_EQ(*mConfigurationChangedTime, when);
197 mConfigurationChangedTime = std::nullopt;
198 }
199
200 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700201 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800202 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800203 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800204 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
205 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
206 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
207 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
208 mLastNotifySwitch = std::nullopt;
209 }
210
chaviwfd6d3512019-03-25 13:23:49 -0700211 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700212 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800213 ASSERT_EQ(touchedToken, mOnPointerDownToken);
214 mOnPointerDownToken.clear();
215 }
216
217 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700218 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800219 ASSERT_TRUE(mOnPointerDownToken == nullptr)
220 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700221 }
222
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700223 // This function must be called soon after the expected ANR timer starts,
224 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500225 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700226 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500227 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800228 std::unique_lock lock(mLock);
229 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 ASSERT_NO_FATAL_FAILURE(
232 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700234 }
235
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000236 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800237 const sp<WindowInfoHandle>& window) {
238 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
239 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
240 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500241 }
242
Prabir Pradhanedd96402022-02-15 01:46:16 -0800243 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
244 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000245 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 std::unique_lock lock(mLock);
247 android::base::ScopedLockAssertion assumeLocked(mLock);
248 AnrResult result;
249 ASSERT_NO_FATAL_FAILURE(result =
250 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000251 ASSERT_EQ(expectedToken, result.token);
252 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500253 }
254
Prabir Pradhanedd96402022-02-15 01:46:16 -0800255 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000256 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500257 std::unique_lock lock(mLock);
258 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800259 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
260 const auto& [token, _] = result;
261 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000262 }
263
Prabir Pradhanedd96402022-02-15 01:46:16 -0800264 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000265 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800266 std::unique_lock lock(mLock);
267 android::base::ScopedLockAssertion assumeLocked(mLock);
268 AnrResult result;
269 ASSERT_NO_FATAL_FAILURE(
270 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000271 ASSERT_EQ(expectedToken, result.token);
272 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 }
274
275 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000276 sp<IBinder> getResponsiveWindowToken() {
277 std::unique_lock lock(mLock);
278 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800279 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
280 const auto& [token, _] = result;
281 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700282 }
283
284 void assertNotifyAnrWasNotCalled() {
285 std::scoped_lock lock(mLock);
286 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_TRUE(mAnrWindows.empty());
288 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 << "ANR was not called, but please also consume the 'connection is responsive' "
290 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700291 }
292
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000293 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800294 std::unique_lock lock(mLock);
295 base::ScopedLockAssertion assumeLocked(mLock);
296
297 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
298 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000299 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800300 enabled;
301 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
303 << ") to be called.";
304 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800305 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000306 auto request = *mPointerCaptureRequest;
307 mPointerCaptureRequest.reset();
308 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800309 }
310
311 void assertSetPointerCaptureNotCalled() {
312 std::unique_lock lock(mLock);
313 base::ScopedLockAssertion assumeLocked(mLock);
314
315 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000316 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800317 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000318 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800319 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800321 }
322
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700323 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
324 const sp<IBinder>& targetToken) {
325 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800326 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800327 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800328 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800329 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800330 }
331
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800332 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
333 std::unique_lock lock(mLock);
334 base::ScopedLockAssertion assumeLocked(mLock);
335 std::optional<sp<IBinder>> receivedToken =
336 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
337 mNotifyInputChannelBroken);
338 ASSERT_TRUE(receivedToken.has_value());
339 ASSERT_EQ(token, *receivedToken);
340 }
341
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800342 /**
343 * Set policy timeout. A value of zero means next key will not be intercepted.
344 */
345 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
346 mInterceptKeyTimeout = timeout;
347 }
348
Josep del Riob3981622023-04-18 15:49:45 +0000349 void assertUserActivityPoked() {
350 std::scoped_lock lock(mLock);
351 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
352 }
353
354 void assertUserActivityNotPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
357 }
358
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000359 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000360 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
361 }
362
363 void assertNotifyDeviceInteractionWasNotCalled() {
364 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
365 }
366
Michael Wrightd02c5b62014-02-10 15:10:22 -0800367private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700368 std::mutex mLock;
369 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
370 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
371 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
372 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800373
Prabir Pradhan99987712020-11-10 18:43:05 -0800374 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000375
376 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800377
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700378 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700379 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800380 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
381 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700382 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800383 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
384 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700385
arthurhungf452d0b2021-01-06 00:19:52 +0800386 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800387 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000388 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800389
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800390 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
391
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000392 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000393
Prabir Pradhanedd96402022-02-15 01:46:16 -0800394 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
395 // for a specific container to become non-empty. When the container is non-empty, return the
396 // first entry from the container and erase it.
397 template <class T>
398 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
399 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
400 // If there is an ANR, Dispatcher won't be idle because there are still events
401 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
402 // before checking if ANR was called.
403 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
404 // to provide it some time to act. 100ms seems reasonable.
405 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
406 const std::chrono::time_point start = std::chrono::steady_clock::now();
407 std::optional<T> token =
408 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
409 if (!token.has_value()) {
410 ADD_FAILURE() << "Did not receive the ANR callback";
411 return {};
412 }
413
414 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
415 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
416 // the dispatcher started counting before this function was called
417 if (std::chrono::abs(timeout - waited) > 100ms) {
418 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
419 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
420 << "ms, but waited "
421 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
422 << "ms instead";
423 }
424 return *token;
425 }
426
427 template <class T>
428 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
429 std::queue<T>& storage,
430 std::unique_lock<std::mutex>& lock,
431 std::condition_variable& condition)
432 REQUIRES(mLock) {
433 condition.wait_for(lock, timeout,
434 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
435 if (storage.empty()) {
436 ADD_FAILURE() << "Did not receive the expected callback";
437 return std::nullopt;
438 }
439 T item = storage.front();
440 storage.pop();
441 return std::make_optional(item);
442 }
443
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600444 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700445 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800446 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800447 }
448
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000449 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800450 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700451 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800452 ASSERT_TRUE(pid.has_value());
453 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700454 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500455 }
456
Prabir Pradhanedd96402022-02-15 01:46:16 -0800457 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000458 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500459 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800460 ASSERT_TRUE(pid.has_value());
461 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500462 mNotifyAnr.notify_all();
463 }
464
465 void notifyNoFocusedWindowAnr(
466 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
467 std::scoped_lock lock(mLock);
468 mAnrApplications.push(applicationHandle);
469 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800470 }
471
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800472 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
473 std::scoped_lock lock(mLock);
474 mBrokenInputChannels.push(connectionToken);
475 mNotifyInputChannelBroken.notify_all();
476 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700479
Chris Yef59a2f42020-10-16 12:55:26 -0700480 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
481 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
482 const std::vector<float>& values) override {}
483
484 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
485 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000486
Chris Yefb552902021-02-03 17:18:37 -0800487 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
488
Prabir Pradhana41d2442023-04-20 21:30:40 +0000489 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700490 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000491 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700492 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000493 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
494 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800495 break;
496 }
497
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700498 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000499 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
500 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800501 break;
502 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700503 default: {
504 ADD_FAILURE() << "Should only filter keys or motions";
505 break;
506 }
Jackal Guof9696682018-10-05 12:23:23 +0800507 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800508 return true;
509 }
510
Prabir Pradhana41d2442023-04-20 21:30:40 +0000511 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
512 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800513 // Clear intercept state when we handled the event.
514 mInterceptKeyTimeout = 0ms;
515 }
516 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800517
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600518 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800519
Prabir Pradhana41d2442023-04-20 21:30:40 +0000520 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800521 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
522 // Clear intercept state so we could dispatch the event in next wake.
523 mInterceptKeyTimeout = 0ms;
524 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525 }
526
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
528 uint32_t) override {
529 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800530 }
531
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600532 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
533 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700534 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800535 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
536 * essentially a passthrough for notifySwitch.
537 */
Harry Cutts33476232023-01-30 19:57:29 +0000538 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800539 }
540
Josep del Riob3981622023-04-18 15:49:45 +0000541 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
542 std::scoped_lock lock(mLock);
543 mPokedUserActivity = true;
544 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800545
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600546 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700547 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700548 mOnPointerDownToken = newToken;
549 }
550
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000551 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800552 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000553 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800554 mPointerCaptureChangedCondition.notify_all();
555 }
556
arthurhungf452d0b2021-01-06 00:19:52 +0800557 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
558 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800559 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800560 mDropTargetWindowToken = token;
561 }
562
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000563 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000564 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000565 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
566 }
567
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700568 void assertFilterInputEventWasCalledInternal(
569 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700570 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800571 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700572 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800573 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800574 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700576} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577
Michael Wrightd02c5b62014-02-10 15:10:22 -0800578// --- InputDispatcherTest ---
579
580class InputDispatcherTest : public testing::Test {
581protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000582 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700583 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800584
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000585 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000586 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
587 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000588 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000589 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700590 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800591 }
592
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000593 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700594 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000595 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700596 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700598
599 /**
600 * Used for debugging when writing the test
601 */
602 void dumpDispatcherState() {
603 std::string dump;
604 mDispatcher->dump(dump);
605 std::stringstream ss(dump);
606 std::string to;
607
608 while (std::getline(ss, to, '\n')) {
609 ALOGE("%s", to.c_str());
610 }
611 }
Vishnu Nair958da932020-08-21 17:12:37 -0700612
Chavi Weingarten847e8512023-03-29 00:26:09 +0000613 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700614 FocusRequest request;
615 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000616 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700617 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
618 request.displayId = window->getInfo()->displayId;
619 mDispatcher->setFocusedWindow(request);
620 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800621};
622
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
624 KeyEvent event;
625
626 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800627 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
628 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000629 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600630 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800631 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000632 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000633 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 << "Should reject key events with undefined action.";
635
636 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800637 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
638 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600639 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800640 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000641 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000642 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800643 << "Should reject key events with ACTION_MULTIPLE.";
644}
645
646TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
647 MotionEvent event;
648 PointerProperties pointerProperties[MAX_POINTERS + 1];
649 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800650 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800651 pointerProperties[i].clear();
652 pointerProperties[i].id = i;
653 pointerCoords[i].clear();
654 }
655
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800656 // Some constants commonly used below
657 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
658 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
659 constexpr int32_t metaState = AMETA_NONE;
660 constexpr MotionClassification classification = MotionClassification::NONE;
661
chaviw9eaa22c2020-07-01 16:21:27 -0700662 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800664 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000665 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700666 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700667 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
668 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000669 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800670 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000671 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000672 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800673 << "Should reject motion events with undefined action.";
674
675 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800676 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800677 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
678 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
679 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
680 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000681 /*pointerCount=*/1, pointerProperties, pointerCoords);
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 motion events with pointer down index too large.";
686
Garfield Tanfbe732e2020-01-24 11:26:14 -0800687 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700688 AMOTION_EVENT_ACTION_POINTER_DOWN |
689 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700690 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
691 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700692 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000693 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800694 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000695 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000696 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800697 << "Should reject motion events with pointer down index too small.";
698
699 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800700 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800701 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
702 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
703 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
704 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000705 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800706 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000707 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000708 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800709 << "Should reject motion events with pointer up index too large.";
710
Garfield Tanfbe732e2020-01-24 11:26:14 -0800711 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700712 AMOTION_EVENT_ACTION_POINTER_UP |
713 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700714 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
715 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700716 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000717 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800718 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000719 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000720 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800721 << "Should reject motion events with pointer up index too small.";
722
723 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800724 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
725 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700726 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700727 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
728 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000729 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800730 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000731 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000732 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800733 << "Should reject motion events with 0 pointers.";
734
Garfield Tanfbe732e2020-01-24 11:26:14 -0800735 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
736 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700737 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700738 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
739 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000740 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800741 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000742 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000743 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800744 << "Should reject motion events with more than MAX_POINTERS pointers.";
745
746 // Rejects motion events with invalid pointer ids.
747 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800748 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
749 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700750 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700751 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
752 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000753 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800754 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000755 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000756 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800757 << "Should reject motion events with pointer ids less than 0.";
758
759 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800760 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
761 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700762 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700763 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
764 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000765 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800766 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000767 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000768 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800769 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
770
771 // Rejects motion events with duplicate pointer ids.
772 pointerProperties[0].id = 1;
773 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800774 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
775 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700776 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700777 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
778 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000779 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000781 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000782 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800783 << "Should reject motion events with duplicate pointer ids.";
784}
785
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800786/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
787
788TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
789 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000790 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800791 ASSERT_TRUE(mDispatcher->waitForIdle());
792
793 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
794}
795
796TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000797 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
798 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000799 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800800
801 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
802 args.policyFlags |= POLICY_FLAG_TRUSTED;
803 mFakePolicy->assertNotifySwitchWasCalled(args);
804}
805
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700806namespace {
807
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700808static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700809// Default input dispatching timeout if there is no focused application or paused window
810// from which to determine an appropriate dispatching timeout.
811static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
812 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
813 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800814
815class FakeApplicationHandle : public InputApplicationHandle {
816public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700817 FakeApplicationHandle() {
818 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700819 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500820 mInfo.dispatchingTimeoutMillis =
821 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700822 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800823 virtual ~FakeApplicationHandle() {}
824
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000825 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700826
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500827 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
828 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700829 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800830};
831
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800832class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800833public:
Garfield Tan15601662020-09-22 15:32:38 -0700834 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800835 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700836 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800837 }
838
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700839 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700840 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700841 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700842 if (!consumeSeq) {
843 return nullptr;
844 }
845 finishEvent(*consumeSeq);
846 return event;
847 }
848
849 /**
850 * Receive an event without acknowledging it.
851 * Return the sequence number that could later be used to send finished signal.
852 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700853 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
854 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800855 uint32_t consumeSeq;
856 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800857
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800858 std::chrono::time_point start = std::chrono::steady_clock::now();
859 status_t status = WOULD_BLOCK;
860 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000861 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800862 &event);
863 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700864 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800865 break;
866 }
867 }
868
869 if (status == WOULD_BLOCK) {
870 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800872 }
873
874 if (status != OK) {
875 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700876 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800877 }
878 if (event == nullptr) {
879 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800881 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882 if (outEvent != nullptr) {
883 *outEvent = event;
884 }
885 return consumeSeq;
886 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800887
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700888 /**
889 * To be used together with "receiveEvent" to complete the consumption of an event.
890 */
891 void finishEvent(uint32_t consumeSeq) {
892 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
893 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800894 }
895
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000896 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
897 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
898 ASSERT_EQ(OK, status);
899 }
900
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700901 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000902 std::optional<int32_t> expectedDisplayId,
903 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700904 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905
906 ASSERT_NE(nullptr, event) << mName.c_str()
907 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800908 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700909 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
910 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800911
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000912 if (expectedDisplayId.has_value()) {
913 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
914 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800915
Tiger Huang8664f8c2018-10-11 19:14:35 +0800916 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700917 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800918 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700919 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000920 if (expectedFlags.has_value()) {
921 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
922 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800923 break;
924 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700925 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800926 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700927 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000928 if (expectedFlags.has_value()) {
929 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
930 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800931 break;
932 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700933 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100934 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
935 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700936 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800937 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
938 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700939 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000940 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
941 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800943 FAIL() << "Use 'consumeDragEvent' for DRAG events";
944 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800945 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800946 }
947
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800948 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700949 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800950
951 if (event == nullptr) {
952 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
953 return nullptr;
954 }
955
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700956 if (event->getType() != InputEventType::MOTION) {
957 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800958 return nullptr;
959 }
960 return static_cast<MotionEvent*>(event);
961 }
962
963 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
964 MotionEvent* motionEvent = consumeMotion();
965 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
966 ASSERT_THAT(*motionEvent, matcher);
967 }
968
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100969 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700970 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100971 ASSERT_NE(nullptr, event) << mName.c_str()
972 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 ASSERT_EQ(InputEventType::FOCUS, event->getType())
974 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100975
976 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
977 << mName.c_str() << ": event displayId should always be NONE.";
978
979 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
980 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100981 }
982
Prabir Pradhan99987712020-11-10 18:43:05 -0800983 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700984 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -0800985 ASSERT_NE(nullptr, event) << mName.c_str()
986 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700987 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
988 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -0800989
990 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
991 << mName.c_str() << ": event displayId should always be NONE.";
992
993 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
994 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
995 }
996
arthurhungb89ccb02020-12-30 16:19:01 +0800997 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700998 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +0800999 ASSERT_NE(nullptr, event) << mName.c_str()
1000 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001001 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001002
1003 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1004 << mName.c_str() << ": event displayId should always be NONE.";
1005
1006 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1007 EXPECT_EQ(isExiting, dragEvent.isExiting());
1008 EXPECT_EQ(x, dragEvent.getX());
1009 EXPECT_EQ(y, dragEvent.getY());
1010 }
1011
Antonio Kantekf16f2832021-09-28 04:39:20 +00001012 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001013 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001014 ASSERT_NE(nullptr, event) << mName.c_str()
1015 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001016 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1017 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001018
1019 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1020 << mName.c_str() << ": event displayId should always be NONE.";
1021 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1022 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1023 }
1024
chaviwd1c23182019-12-20 18:44:56 -08001025 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001026 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001027 if (event == nullptr) {
1028 return;
1029 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001030 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001031 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1032 ADD_FAILURE() << "Received key event "
1033 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001034 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001035 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1036 ADD_FAILURE() << "Received motion event "
1037 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001038 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001039 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1040 ADD_FAILURE() << "Received focus event, hasFocus = "
1041 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001042 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001043 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1044 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1045 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001046 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001047 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1048 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1049 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001050 }
1051 FAIL() << mName.c_str()
1052 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001053 }
1054
1055 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1056
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001057 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1058
chaviwd1c23182019-12-20 18:44:56 -08001059protected:
1060 std::unique_ptr<InputConsumer> mConsumer;
1061 PreallocatedInputEventFactory mEventFactory;
1062
1063 std::string mName;
1064};
1065
chaviw3277faf2021-05-19 16:45:23 -05001066class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001067public:
1068 static const int32_t WIDTH = 600;
1069 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001070
Chris Yea209fde2020-07-22 13:54:51 -07001071 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001072 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001073 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001074 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001075 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001076 base::Result<std::unique_ptr<InputChannel>> channel =
1077 dispatcher->createInputChannel(name);
1078 token = (*channel)->getConnectionToken();
1079 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001080 }
1081
1082 inputApplicationHandle->updateInfo();
1083 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1084
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001085 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001086 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001087 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001088 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001089 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001090 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001091 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001092 mInfo.globalScaleFactor = 1.0;
1093 mInfo.touchableRegion.clear();
1094 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001095 mInfo.ownerPid = WINDOW_PID;
1096 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001097 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001098 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001099 }
1100
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001101 sp<FakeWindowHandle> clone(int32_t displayId) {
1102 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1103 handle->mInfo = mInfo;
1104 handle->mInfo.displayId = displayId;
1105 handle->mInfo.id = sId++;
1106 handle->mInputReceiver = mInputReceiver;
1107 return handle;
1108 }
1109
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001110 void setTouchable(bool touchable) {
1111 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1112 }
chaviwd1c23182019-12-20 18:44:56 -08001113
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001114 void setFocusable(bool focusable) {
1115 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1116 }
1117
1118 void setVisible(bool visible) {
1119 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1120 }
Vishnu Nair958da932020-08-21 17:12:37 -07001121
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001122 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001123 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001124 }
1125
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001126 void setPaused(bool paused) {
1127 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1128 }
1129
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001130 void setPreventSplitting(bool preventSplitting) {
1131 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001132 }
1133
1134 void setSlippery(bool slippery) {
1135 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1136 }
1137
1138 void setWatchOutsideTouch(bool watchOutside) {
1139 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1140 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001141
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001142 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1143
1144 void setInterceptsStylus(bool interceptsStylus) {
1145 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1146 }
1147
1148 void setDropInput(bool dropInput) {
1149 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1150 }
1151
1152 void setDropInputIfObscured(bool dropInputIfObscured) {
1153 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1154 }
1155
1156 void setNoInputChannel(bool noInputChannel) {
1157 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1158 }
1159
Josep del Riob3981622023-04-18 15:49:45 +00001160 void setDisableUserActivity(bool disableUserActivity) {
1161 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1162 }
1163
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001164 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1165
chaviw3277faf2021-05-19 16:45:23 -05001166 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001167
Bernardo Rufino7393d172021-02-26 13:56:11 +00001168 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1169
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001170 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001171 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001172 mInfo.touchableRegion.clear();
1173 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001174
1175 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1176 ui::Transform translate;
1177 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1178 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001179 }
1180
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001181 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1182
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001183 void setIsWallpaper(bool isWallpaper) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1185 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001186
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001187 void setDupTouchToWallpaper(bool hasWallpaper) {
1188 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1189 }
chaviwd1c23182019-12-20 18:44:56 -08001190
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001191 void setTrustedOverlay(bool trustedOverlay) {
1192 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1193 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001194
chaviw9eaa22c2020-07-01 16:21:27 -07001195 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1196 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1197 }
1198
1199 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001200
yunho.shinf4a80b82020-11-16 21:13:57 +09001201 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1202
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001203 KeyEvent* consumeKey() {
1204 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1205 if (event == nullptr) {
1206 ADD_FAILURE() << "Consume failed : no event";
1207 return nullptr;
1208 }
1209 if (event->getType() != InputEventType::KEY) {
1210 ADD_FAILURE() << "Instead of key event, got " << *event;
1211 return nullptr;
1212 }
1213 return static_cast<KeyEvent*>(event);
1214 }
1215
1216 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1217 KeyEvent* keyEvent = consumeKey();
1218 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1219 ASSERT_THAT(*keyEvent, matcher);
1220 }
1221
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001222 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001223 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001224 }
1225
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001226 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001227 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001228 }
1229
Svet Ganov5d3bc372020-01-26 23:11:07 -08001230 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001231 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001232 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1233 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001234 }
1235
1236 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001237 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001238 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1239 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001240 }
1241
1242 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001243 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001244 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1245 }
1246
1247 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1248 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001249 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001250 expectedFlags);
1251 }
1252
Svet Ganov5d3bc372020-01-26 23:11:07 -08001253 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001254 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1255 int32_t expectedFlags = 0) {
1256 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1257 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001258 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001259 }
1260
1261 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001262 int32_t expectedFlags = 0) {
1263 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1264 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001265 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001266 }
1267
1268 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001269 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001270 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001271 expectedFlags);
1272 }
1273
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001274 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1275 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001276 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001277 expectedFlags);
1278 }
1279
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001280 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1281 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 MotionEvent* motionEvent = consumeMotion();
1283 ASSERT_NE(nullptr, motionEvent);
1284 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1285 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1286 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001287 }
1288
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001289 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1290 ASSERT_NE(mInputReceiver, nullptr)
1291 << "Cannot consume events from a window with no receiver";
1292 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1293 }
1294
Prabir Pradhan99987712020-11-10 18:43:05 -08001295 void consumeCaptureEvent(bool hasCapture) {
1296 ASSERT_NE(mInputReceiver, nullptr)
1297 << "Cannot consume events from a window with no receiver";
1298 mInputReceiver->consumeCaptureEvent(hasCapture);
1299 }
1300
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001301 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1302 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001303 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001304 ASSERT_THAT(*motionEvent, matcher);
1305 }
1306
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001307 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001308 std::optional<int32_t> expectedDisplayId,
1309 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001310 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1311 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1312 expectedFlags);
1313 }
1314
arthurhungb89ccb02020-12-30 16:19:01 +08001315 void consumeDragEvent(bool isExiting, float x, float y) {
1316 mInputReceiver->consumeDragEvent(isExiting, x, y);
1317 }
1318
Antonio Kantekf16f2832021-09-28 04:39:20 +00001319 void consumeTouchModeEvent(bool inTouchMode) {
1320 ASSERT_NE(mInputReceiver, nullptr)
1321 << "Cannot consume events from a window with no receiver";
1322 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1323 }
1324
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001325 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001326 if (mInputReceiver == nullptr) {
1327 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1328 return std::nullopt;
1329 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001330 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001331 }
1332
1333 void finishEvent(uint32_t sequenceNum) {
1334 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1335 mInputReceiver->finishEvent(sequenceNum);
1336 }
1337
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001338 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1339 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1340 mInputReceiver->sendTimeline(inputEventId, timeline);
1341 }
1342
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001343 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001344 if (mInputReceiver == nullptr) {
1345 return nullptr;
1346 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001347 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001348 }
1349
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001350 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001351 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001352 if (event == nullptr) {
1353 ADD_FAILURE() << "Consume failed : no event";
1354 return nullptr;
1355 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001356 if (event->getType() != InputEventType::MOTION) {
1357 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001358 return nullptr;
1359 }
1360 return static_cast<MotionEvent*>(event);
1361 }
1362
Arthur Hungb92218b2018-08-14 12:00:21 +08001363 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001364 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001365 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001366 return; // Can't receive events if the window does not have input channel
1367 }
1368 ASSERT_NE(nullptr, mInputReceiver)
1369 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001370 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001371 }
1372
chaviwaf87b3e2019-10-01 16:59:28 -07001373 sp<IBinder> getToken() { return mInfo.token; }
1374
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001375 const std::string& getName() { return mName; }
1376
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001377 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001378 mInfo.ownerPid = ownerPid;
1379 mInfo.ownerUid = ownerUid;
1380 }
1381
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001382 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001383
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001384 void destroyReceiver() { mInputReceiver = nullptr; }
1385
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001386 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1387
chaviwd1c23182019-12-20 18:44:56 -08001388private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001389 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001390 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001391 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001392 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001393 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001394};
1395
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001396std::atomic<int32_t> FakeWindowHandle::sId{1};
1397
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001398class FakeMonitorReceiver {
1399public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001400 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001401 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001402 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001403 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1404 }
1405
1406 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1407
1408 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1409 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1410 expectedFlags);
1411 }
1412
1413 std::optional<int32_t> receiveEvent() {
1414 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1415 }
1416
1417 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1418
1419 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1420 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1421 expectedDisplayId, expectedFlags);
1422 }
1423
1424 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1425 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1426 expectedDisplayId, expectedFlags);
1427 }
1428
1429 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1430 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1431 expectedDisplayId, expectedFlags);
1432 }
1433
1434 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1435 mInputReceiver->consumeMotionEvent(
1436 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1437 WithDisplayId(expectedDisplayId),
1438 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1439 }
1440
1441 void consumeMotionPointerDown(int32_t pointerIdx) {
1442 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1443 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1444 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1445 /*expectedFlags=*/0);
1446 }
1447
1448 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1449 mInputReceiver->consumeMotionEvent(matcher);
1450 }
1451
1452 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1453
1454 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1455
1456private:
1457 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1458};
1459
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001460static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001461 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001462 int32_t displayId = ADISPLAY_ID_NONE,
1463 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001464 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001465 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001466 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001467 KeyEvent event;
1468 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1469
1470 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001471 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001472 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1473 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001474
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001475 if (!allowKeyRepeat) {
1476 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1477 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001478 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001479 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001480}
1481
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001482static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1483 InputEventInjectionResult result =
1484 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1485 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1486 if (result != InputEventInjectionResult::TIMED_OUT) {
1487 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1488 }
1489}
1490
1491static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001492 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001493 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001494}
1495
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1497// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1498// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001499static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1500 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001501 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001502 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001503 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001504}
1505
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001506static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001507 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001508 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001509}
1510
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001511static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001512 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001513 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001514 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001515 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001516 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1517 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001518}
1519
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001520static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001521 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1522 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001523 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001524 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1525 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001526 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001527 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001528 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001529 MotionEventBuilder motionBuilder =
1530 MotionEventBuilder(action, source)
1531 .displayId(displayId)
1532 .eventTime(eventTime)
1533 .rawXCursorPosition(cursorPosition.x)
1534 .rawYCursorPosition(cursorPosition.y)
1535 .pointer(
1536 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1537 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1538 motionBuilder.downTime(eventTime);
1539 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001540
1541 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001542 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1543 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001544}
1545
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001546static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1547 int32_t displayId,
1548 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001549 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001550}
1551
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001552static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1553 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001554 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001555 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001556}
1557
Jackal Guof9696682018-10-05 12:23:23 +08001558static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1559 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1560 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001561 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001562 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1563 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001564
1565 return args;
1566}
1567
Josep del Riob3981622023-04-18 15:49:45 +00001568static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1569 int32_t displayId = ADISPLAY_ID_NONE) {
1570 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1571 // Define a valid key event.
1572 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001573 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001574 currentTime);
1575
1576 return args;
1577}
1578
1579static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1580 int32_t displayId = ADISPLAY_ID_NONE) {
1581 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1582 // Define a valid key event.
1583 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001584 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001585 AMETA_NONE, currentTime);
1586
1587 return args;
1588}
1589
Prabir Pradhan678438e2023-04-13 19:32:51 +00001590[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1591 int32_t displayId,
1592 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001593 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001594 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1595 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1596 }
1597
chaviwd1c23182019-12-20 18:44:56 -08001598 PointerProperties pointerProperties[pointerCount];
1599 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001600
chaviwd1c23182019-12-20 18:44:56 -08001601 for (size_t i = 0; i < pointerCount; i++) {
1602 pointerProperties[i].clear();
1603 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001604 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001605
chaviwd1c23182019-12-20 18:44:56 -08001606 pointerCoords[i].clear();
1607 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1608 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1609 }
Jackal Guof9696682018-10-05 12:23:23 +08001610
1611 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1612 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001613 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001614 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1615 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001616 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001617 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001618 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001619 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001620
1621 return args;
1622}
1623
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001624static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1625 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1626}
1627
chaviwd1c23182019-12-20 18:44:56 -08001628static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1629 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1630}
1631
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001632static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1633 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001634 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001635}
1636
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001637} // namespace
1638
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001639/**
1640 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1641 * broken channel.
1642 */
1643TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1645 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001646 sp<FakeWindowHandle>::make(application, mDispatcher,
1647 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001648
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001650
1651 // Window closes its channel, but the window remains.
1652 window->destroyReceiver();
1653 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1654}
1655
Arthur Hungb92218b2018-08-14 12:00:21 +08001656TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001658 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1659 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001660
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001661 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001663 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001665
1666 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001667 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001668}
1669
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001670TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001672 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1673 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001674
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001675 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001676 // Inject a MotionEvent to an unknown display.
1677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001678 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1680
1681 // Window should receive motion event.
1682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1683}
1684
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001685/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001686 * Calling onWindowInfosChanged once should not cause any issues.
1687 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688 * called twice.
1689 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001690TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001692 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1693 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001694 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001696 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001698 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001699 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701
1702 // Window should receive motion event.
1703 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1704}
1705
1706/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001707 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708 */
1709TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1712 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001715 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1716 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001718 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721
1722 // Window should receive motion event.
1723 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1724}
1725
Arthur Hungb92218b2018-08-14 12:00:21 +08001726// The foreground window should receive the first touch down event.
1727TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001729 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001730 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001731 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001733
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001734 mDispatcher->onWindowInfosChanged(
1735 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001739
1740 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001741 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001742 windowSecond->assertNoEvents();
1743}
1744
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001745/**
1746 * Two windows: A top window, and a wallpaper behind the window.
1747 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1748 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001749 * 1. foregroundWindow <-- dup touch to wallpaper
1750 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001751 */
1752TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1754 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001755 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001756 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001757 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001758 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001759 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001760
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001761 mDispatcher->onWindowInfosChanged(
1762 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001764 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001765 {100, 200}))
1766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1767
1768 // Both foreground window and its wallpaper should receive the touch down
1769 foregroundWindow->consumeMotionDown();
1770 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1771
1772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001773 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001774 ADISPLAY_ID_DEFAULT, {110, 200}))
1775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1776
1777 foregroundWindow->consumeMotionMove();
1778 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1779
1780 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001781 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001782 foregroundWindow->consumeMotionCancel();
1783 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1784 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1785}
1786
1787/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001788 * Two fingers down on the window, and lift off the first finger.
1789 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1790 * contains a single pointer.
1791 */
1792TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1794 sp<FakeWindowHandle> window =
1795 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1796
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001797 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001798 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1800 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1801 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001802 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001803 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1804 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1805 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1806 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001807 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001808 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1809 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1810 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1811 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001812 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1813 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1814 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1815
1816 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001817 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001818 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1819 window->consumeMotionEvent(
1820 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1821}
1822
1823/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001824 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1825 * with the following differences:
1826 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1827 * clean up the connection.
1828 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1829 * Ensure that there's no crash in the dispatcher.
1830 */
1831TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1832 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1833 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001834 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001835 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001836 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001837 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001838 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001839
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged(
1841 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001843 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001844 {100, 200}))
1845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1846
1847 // Both foreground window and its wallpaper should receive the touch down
1848 foregroundWindow->consumeMotionDown();
1849 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1850
1851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001852 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 ADISPLAY_ID_DEFAULT, {110, 200}))
1854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1855
1856 foregroundWindow->consumeMotionMove();
1857 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1858
1859 // Wallpaper closes its channel, but the window remains.
1860 wallpaperWindow->destroyReceiver();
1861 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1862
1863 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1864 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001865 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001866 foregroundWindow->consumeMotionCancel();
1867}
1868
Arthur Hungc539dbb2022-12-08 07:45:36 +00001869class ShouldSplitTouchFixture : public InputDispatcherTest,
1870 public ::testing::WithParamInterface<bool> {};
1871INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1872 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001873/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001874 * A single window that receives touch (on top), and a wallpaper window underneath it.
1875 * The top window gets a multitouch gesture.
1876 * Ensure that wallpaper gets the same gesture.
1877 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001878TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001880 sp<FakeWindowHandle> foregroundWindow =
1881 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1882 foregroundWindow->setDupTouchToWallpaper(true);
1883 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001884
1885 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001886 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001887 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001889 mDispatcher->onWindowInfosChanged(
1890 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891
1892 // Touch down on top window
1893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001894 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001895 {100, 100}))
1896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1897
1898 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001899 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1901
1902 // Second finger down on the top window
1903 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001904 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001906 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1907 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001908 .build();
1909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001910 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911 InputEventInjectionSync::WAIT_FOR_RESULT))
1912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1913
Harry Cutts33476232023-01-30 19:57:29 +00001914 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1915 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001917
1918 const MotionEvent secondFingerUpEvent =
1919 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1920 .displayId(ADISPLAY_ID_DEFAULT)
1921 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001922 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1923 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001924 .build();
1925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001926 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001927 InputEventInjectionSync::WAIT_FOR_RESULT))
1928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1929 foregroundWindow->consumeMotionPointerUp(0);
1930 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1931
1932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001933 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001934 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1935 AINPUT_SOURCE_TOUCHSCREEN)
1936 .displayId(ADISPLAY_ID_DEFAULT)
1937 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001938 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001939 .x(100)
1940 .y(100))
1941 .build(),
1942 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1944 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1945 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946}
1947
1948/**
1949 * Two windows: a window on the left and window on the right.
1950 * A third window, wallpaper, is behind both windows, and spans both top windows.
1951 * The first touch down goes to the left window. A second pointer touches down on the right window.
1952 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1953 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1954 * ACTION_POINTER_DOWN(1).
1955 */
1956TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1958 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001959 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001961 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962
1963 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001964 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001966 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001967
1968 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001969 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001970 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001971 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001973 mDispatcher->onWindowInfosChanged(
1974 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1975 {},
1976 0,
1977 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978
1979 // Touch down on left window
1980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001981 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001982 {100, 100}))
1983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1984
1985 // Both foreground window and its wallpaper should receive the touch down
1986 leftWindow->consumeMotionDown();
1987 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1988
1989 // Second finger down on the right window
1990 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001991 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001992 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001993 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1994 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995 .build();
1996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001997 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 InputEventInjectionSync::WAIT_FOR_RESULT))
1999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2000
2001 leftWindow->consumeMotionMove();
2002 // Since the touch is split, right window gets ACTION_DOWN
2003 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002004 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002005 expectedWallpaperFlags);
2006
2007 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002008 mDispatcher->onWindowInfosChanged(
2009 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002010 leftWindow->consumeMotionCancel();
2011 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2012 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2013
2014 // The pointer that's still down on the right window moves, and goes to the right window only.
2015 // As far as the dispatcher's concerned though, both pointers are still present.
2016 const MotionEvent secondFingerMoveEvent =
2017 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2018 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002019 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2020 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 .build();
2022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002023 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002024 InputEventInjectionSync::WAIT_FOR_RESULT));
2025 rightWindow->consumeMotionMove();
2026
2027 leftWindow->assertNoEvents();
2028 rightWindow->assertNoEvents();
2029 wallpaperWindow->assertNoEvents();
2030}
2031
Arthur Hungc539dbb2022-12-08 07:45:36 +00002032/**
2033 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2034 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2035 * The right window should receive ACTION_DOWN.
2036 */
2037TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002039 sp<FakeWindowHandle> leftWindow =
2040 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2041 leftWindow->setFrame(Rect(0, 0, 200, 200));
2042 leftWindow->setDupTouchToWallpaper(true);
2043 leftWindow->setSlippery(true);
2044
2045 sp<FakeWindowHandle> rightWindow =
2046 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2047 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002048
2049 sp<FakeWindowHandle> wallpaperWindow =
2050 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2051 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002052
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002053 mDispatcher->onWindowInfosChanged(
2054 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2055 {},
2056 0,
2057 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002058
Arthur Hungc539dbb2022-12-08 07:45:36 +00002059 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002061 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002062 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002064
2065 // Both foreground window and its wallpaper should receive the touch down
2066 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002067 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2068
Arthur Hungc539dbb2022-12-08 07:45:36 +00002069 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002071 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002072 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2074
Arthur Hungc539dbb2022-12-08 07:45:36 +00002075 leftWindow->consumeMotionCancel();
2076 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2077 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002078}
2079
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002080/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002081 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2082 * interactive, it might stop sending this flag.
2083 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2084 * to have a consistent input stream.
2085 *
2086 * Test procedure:
2087 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2088 * DOWN (new gesture).
2089 *
2090 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2091 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2092 *
2093 * We technically just need a single window here, but we are using two windows (spy on top and a
2094 * regular window below) to emulate the actual situation where it happens on the device.
2095 */
2096TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2098 sp<FakeWindowHandle> spyWindow =
2099 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2100 spyWindow->setFrame(Rect(0, 0, 200, 200));
2101 spyWindow->setTrustedOverlay(true);
2102 spyWindow->setSpy(true);
2103
2104 sp<FakeWindowHandle> window =
2105 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2106 window->setFrame(Rect(0, 0, 200, 200));
2107
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002108 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002109 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002110
2111 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002112 mDispatcher->notifyMotion(
2113 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2114 .deviceId(touchDeviceId)
2115 .policyFlags(DEFAULT_POLICY_FLAGS)
2116 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2117 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002118
Prabir Pradhan678438e2023-04-13 19:32:51 +00002119 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2120 .deviceId(touchDeviceId)
2121 .policyFlags(DEFAULT_POLICY_FLAGS)
2122 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2123 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2124 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002125 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2126 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2127 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2128 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2129
2130 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002131 mDispatcher->notifyMotion(
2132 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2133 .deviceId(touchDeviceId)
2134 .policyFlags(0)
2135 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2136 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2137 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002138 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2139 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2140
2141 // We don't need to reset the device to reproduce the issue, but the reset event typically
2142 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002143 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002144
2145 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002146 mDispatcher->notifyMotion(
2147 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2148 .deviceId(touchDeviceId)
2149 .policyFlags(DEFAULT_POLICY_FLAGS)
2150 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2151 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002152 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2153 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2154
2155 // No more events
2156 spyWindow->assertNoEvents();
2157 window->assertNoEvents();
2158}
2159
2160/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002161 * Two windows: a window on the left and a window on the right.
2162 * Mouse is hovered from the right window into the left window.
2163 * Next, we tap on the left window, where the cursor was last seen.
2164 * The second tap is done onto the right window.
2165 * The mouse and tap are from two different devices.
2166 * We technically don't need to set the downtime / eventtime for these events, but setting these
2167 * explicitly helps during debugging.
2168 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2169 * In the buggy implementation, a tap on the right window would cause a crash.
2170 */
2171TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2173 sp<FakeWindowHandle> leftWindow =
2174 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2175 leftWindow->setFrame(Rect(0, 0, 200, 200));
2176
2177 sp<FakeWindowHandle> rightWindow =
2178 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2179 rightWindow->setFrame(Rect(200, 0, 400, 200));
2180
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002181 mDispatcher->onWindowInfosChanged(
2182 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002183 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2184 // stale.
2185 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2186 const int32_t mouseDeviceId = 6;
2187 const int32_t touchDeviceId = 4;
2188 // Move the cursor from right
2189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002190 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002191 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2192 AINPUT_SOURCE_MOUSE)
2193 .deviceId(mouseDeviceId)
2194 .downTime(baseTime + 10)
2195 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002196 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002197 .build()));
2198 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2199
2200 // .. to the left window
2201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002202 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002203 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2204 AINPUT_SOURCE_MOUSE)
2205 .deviceId(mouseDeviceId)
2206 .downTime(baseTime + 10)
2207 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002208 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002209 .build()));
2210 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2211 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2212 // Now tap the left window
2213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002214 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002215 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2216 AINPUT_SOURCE_TOUCHSCREEN)
2217 .deviceId(touchDeviceId)
2218 .downTime(baseTime + 40)
2219 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002220 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002221 .build()));
2222 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2223 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2224
2225 // release tap
2226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002227 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002228 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2229 AINPUT_SOURCE_TOUCHSCREEN)
2230 .deviceId(touchDeviceId)
2231 .downTime(baseTime + 40)
2232 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002233 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002234 .build()));
2235 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2236
2237 // Tap the window on the right
2238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2241 AINPUT_SOURCE_TOUCHSCREEN)
2242 .deviceId(touchDeviceId)
2243 .downTime(baseTime + 60)
2244 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002245 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002246 .build()));
2247 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2248
2249 // release tap
2250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002251 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002252 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2253 AINPUT_SOURCE_TOUCHSCREEN)
2254 .deviceId(touchDeviceId)
2255 .downTime(baseTime + 60)
2256 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002257 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002258 .build()));
2259 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2260
2261 // No more events
2262 leftWindow->assertNoEvents();
2263 rightWindow->assertNoEvents();
2264}
2265
2266/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002267 * Start hovering in a window. While this hover is still active, make another window appear on top.
2268 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2269 * While the top window is present, the hovering is stopped.
2270 * Later, hovering gets resumed again.
2271 * Ensure that new hover gesture is handled correctly.
2272 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2273 * to the window that's currently being hovered over.
2274 */
2275TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2277 sp<FakeWindowHandle> window =
2278 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2279 window->setFrame(Rect(0, 0, 200, 200));
2280
2281 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002282 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002283
2284 // Start hovering in the window
2285 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2286 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2287 .build());
2288 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2289
2290 // Now, an obscuring window appears!
2291 sp<FakeWindowHandle> obscuringWindow =
2292 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2293 ADISPLAY_ID_DEFAULT,
2294 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2295 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2296 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2297 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2298 obscuringWindow->setNoInputChannel(true);
2299 obscuringWindow->setFocusable(false);
2300 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002301 mDispatcher->onWindowInfosChanged(
2302 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002303
2304 // While this new obscuring window is present, the hovering is stopped
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2307 .build());
2308 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2309
2310 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002311 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002312
2313 // And a new hover gesture starts.
2314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2315 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2316 .build());
2317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2318}
2319
2320/**
2321 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2322 * the obscuring window.
2323 */
2324TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2326 sp<FakeWindowHandle> window =
2327 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2328 window->setFrame(Rect(0, 0, 200, 200));
2329
2330 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002331 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002332
2333 // Start hovering in the window
2334 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2335 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2336 .build());
2337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2338
2339 // Now, an obscuring window appears!
2340 sp<FakeWindowHandle> obscuringWindow =
2341 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2342 ADISPLAY_ID_DEFAULT,
2343 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2344 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2345 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2346 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2347 obscuringWindow->setNoInputChannel(true);
2348 obscuringWindow->setFocusable(false);
2349 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002350 mDispatcher->onWindowInfosChanged(
2351 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002352
2353 // While this new obscuring window is present, the hovering continues. The event can't go to the
2354 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2355 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2356 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2357 .build());
2358 obscuringWindow->assertNoEvents();
2359 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2360
2361 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002362 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002363
2364 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2365 // so it should generate a HOVER_ENTER
2366 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2367 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2368 .build());
2369 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2370
2371 // Now the MOVE should be getting dispatched normally
2372 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2373 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2374 .build());
2375 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2376}
2377
2378/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002379 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2380 * events are delivered to the window.
2381 */
2382TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2384 sp<FakeWindowHandle> window =
2385 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2386 window->setFrame(Rect(0, 0, 200, 200));
2387 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2388
2389 // Start hovering in the window
2390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2391 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2392 .build());
2393 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2394
2395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2396 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2397 .build());
2398 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2399
2400 // Scroll with the mouse
2401 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2402 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2403 .build());
2404 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2405}
2406
2407using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2408
2409/**
2410 * One window. Stylus down on the window. Next, touch from another device goes down.
2411 */
2412TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
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 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2419
2420 constexpr int32_t touchDeviceId = 4;
2421 constexpr int32_t stylusDeviceId = 2;
2422
2423 // Stylus down
2424 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2425 .deviceId(stylusDeviceId)
2426 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2427 .build());
2428 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2429
2430 // Touch down
2431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2432 .deviceId(touchDeviceId)
2433 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2434 .build());
2435 // Touch cancels stylus
2436 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2437 WithCoords(100, 110)));
2438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2439 WithCoords(140, 145)));
2440
2441 // Touch move
2442 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2443 .deviceId(touchDeviceId)
2444 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2445 .build());
2446 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2447 WithCoords(141, 146)));
2448
2449 // Subsequent stylus movements are dropped
2450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2451 .deviceId(stylusDeviceId)
2452 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2453 .build());
2454 window->assertNoEvents();
2455}
2456
2457/**
2458 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2459 * down.
2460 * Similar test as above, but with added SPY window.
2461 */
2462TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 sp<FakeWindowHandle> spyWindow =
2467 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2468 spyWindow->setFrame(Rect(0, 0, 200, 200));
2469 spyWindow->setTrustedOverlay(true);
2470 spyWindow->setSpy(true);
2471 window->setFrame(Rect(0, 0, 200, 200));
2472
2473 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2474
2475 constexpr int32_t touchDeviceId = 4;
2476 constexpr int32_t stylusDeviceId = 2;
2477
2478 // Stylus down
2479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2480 .deviceId(stylusDeviceId)
2481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2482 .build());
2483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2484 spyWindow->consumeMotionEvent(
2485 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2486
2487 // Touch down
2488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2491 .build());
2492
2493 // Touch move
2494 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2495 .deviceId(touchDeviceId)
2496 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2497 .build());
2498 window->consumeMotionEvent(
2499 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2500 spyWindow->consumeMotionEvent(
2501 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2502 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2503 spyWindow->consumeMotionEvent(
2504 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2505 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2506 spyWindow->consumeMotionEvent(
2507 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2508 // Subsequent stylus movements are dropped
2509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2510 .deviceId(stylusDeviceId)
2511 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2512 .build());
2513
2514 window->assertNoEvents();
2515 spyWindow->assertNoEvents();
2516}
2517
2518/**
2519 * One window. Stylus hover on the window. Next, touch from another device goes down.
2520 */
2521TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2522 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2523 sp<FakeWindowHandle> window =
2524 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2525 window->setFrame(Rect(0, 0, 200, 200));
2526
2527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2528
2529 constexpr int32_t touchDeviceId = 4;
2530 constexpr int32_t stylusDeviceId = 2;
2531
2532 // Stylus down on the window
2533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2534 .deviceId(stylusDeviceId)
2535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2536 .build());
2537 window->consumeMotionEvent(
2538 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2539
2540 // Touch down on window
2541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2542 .deviceId(touchDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2544 .build());
2545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2546 .deviceId(touchDeviceId)
2547 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2548 .build());
2549 window->consumeMotionEvent(
2550 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2552 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2553 // Subsequent stylus movements are ignored
2554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2555 .deviceId(stylusDeviceId)
2556 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2557 .build());
2558 window->assertNoEvents();
2559}
2560
2561/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002562 * Two windows: a window on the left and a window on the right.
2563 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2564 * down. Then, on the left window, also place second touch pointer down.
2565 * This test tries to reproduce a crash.
2566 * In the buggy implementation, second pointer down on the left window would cause a crash.
2567 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002568TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2570 sp<FakeWindowHandle> leftWindow =
2571 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2572 leftWindow->setFrame(Rect(0, 0, 200, 200));
2573
2574 sp<FakeWindowHandle> rightWindow =
2575 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2576 rightWindow->setFrame(Rect(200, 0, 400, 200));
2577
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002578 mDispatcher->onWindowInfosChanged(
2579 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002580
2581 const int32_t touchDeviceId = 4;
2582 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002583
2584 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2586 .deviceId(mouseDeviceId)
2587 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2588 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002589 leftWindow->consumeMotionEvent(
2590 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2591
2592 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002593 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2594 .deviceId(mouseDeviceId)
2595 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2596 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2597 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002598
2599 leftWindow->consumeMotionEvent(
2600 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2601 leftWindow->consumeMotionEvent(
2602 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2603
Prabir Pradhan678438e2023-04-13 19:32:51 +00002604 mDispatcher->notifyMotion(
2605 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2606 .deviceId(mouseDeviceId)
2607 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2608 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2609 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2610 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002611 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2612
2613 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002614 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2615 .deviceId(touchDeviceId)
2616 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2617 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002618 leftWindow->consumeMotionEvent(
2619 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002620 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2621
2622 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002623 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2624 .deviceId(touchDeviceId)
2625 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2626 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2627 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002628 leftWindow->consumeMotionEvent(
2629 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2630 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2631 // current implementation.
2632 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2633 rightWindow->consumeMotionEvent(
2634 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2635
2636 leftWindow->assertNoEvents();
2637 rightWindow->assertNoEvents();
2638}
2639
2640/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002641 * Two windows: a window on the left and a window on the right.
2642 * Mouse is hovered on the left window and stylus is hovered on the right window.
2643 */
2644TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2646 sp<FakeWindowHandle> leftWindow =
2647 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2648 leftWindow->setFrame(Rect(0, 0, 200, 200));
2649
2650 sp<FakeWindowHandle> rightWindow =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2652 rightWindow->setFrame(Rect(200, 0, 400, 200));
2653
2654 mDispatcher->onWindowInfosChanged(
2655 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2656
2657 const int32_t stylusDeviceId = 3;
2658 const int32_t mouseDeviceId = 6;
2659
2660 // Start hovering over the left window
2661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2662 .deviceId(mouseDeviceId)
2663 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2664 .build());
2665 leftWindow->consumeMotionEvent(
2666 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2667
2668 // Stylus hovered on right window
2669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2670 .deviceId(stylusDeviceId)
2671 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2672 .build());
2673 leftWindow->consumeMotionEvent(
2674 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2675 rightWindow->consumeMotionEvent(
2676 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2677
2678 // Subsequent HOVER_MOVE events are dispatched correctly.
2679 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2680 .deviceId(mouseDeviceId)
2681 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2682 .build());
2683 leftWindow->consumeMotionEvent(
2684 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2685 rightWindow->consumeMotionEvent(
2686 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2687
2688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2689 .deviceId(stylusDeviceId)
2690 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2691 .build());
2692 leftWindow->consumeMotionEvent(
2693 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2694 rightWindow->consumeMotionEvent(
2695 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2696
2697 leftWindow->assertNoEvents();
2698 rightWindow->assertNoEvents();
2699}
2700
2701/**
2702 * Three windows: a window on the left and a window on the right.
2703 * And a spy window that's positioned above all of them.
2704 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2705 * Check the stream that's received by the spy.
2706 */
2707TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2709
2710 sp<FakeWindowHandle> spyWindow =
2711 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2712 spyWindow->setFrame(Rect(0, 0, 400, 400));
2713 spyWindow->setTrustedOverlay(true);
2714 spyWindow->setSpy(true);
2715
2716 sp<FakeWindowHandle> leftWindow =
2717 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2718 leftWindow->setFrame(Rect(0, 0, 200, 200));
2719
2720 sp<FakeWindowHandle> rightWindow =
2721 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2722
2723 rightWindow->setFrame(Rect(200, 0, 400, 200));
2724
2725 mDispatcher->onWindowInfosChanged(
2726 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2727
2728 const int32_t stylusDeviceId = 1;
2729 const int32_t touchDeviceId = 2;
2730
2731 // Stylus down on the left window
2732 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2733 .deviceId(stylusDeviceId)
2734 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2735 .build());
2736 leftWindow->consumeMotionEvent(
2737 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2738 spyWindow->consumeMotionEvent(
2739 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2740
2741 // Touch down on the right window
2742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2743 .deviceId(touchDeviceId)
2744 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2745 .build());
2746 leftWindow->consumeMotionEvent(
2747 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2748 spyWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2750 rightWindow->consumeMotionEvent(
2751 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2752 spyWindow->consumeMotionEvent(
2753 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2754
2755 // Stylus movements continue, but are ignored because the touch went down more recently.
2756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2757 .deviceId(stylusDeviceId)
2758 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2759 .build());
2760
2761 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2762 .deviceId(touchDeviceId)
2763 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2764 .build());
2765 rightWindow->consumeMotionEvent(
2766 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2767 spyWindow->consumeMotionEvent(
2768 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2769
2770 spyWindow->assertNoEvents();
2771 leftWindow->assertNoEvents();
2772 rightWindow->assertNoEvents();
2773}
2774
2775/**
2776 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2777 * both.
2778 * Check hover in left window and touch down in the right window.
2779 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2780 */
2781TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2782 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2783
2784 sp<FakeWindowHandle> spyWindow =
2785 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2786 spyWindow->setFrame(Rect(0, 0, 400, 400));
2787 spyWindow->setTrustedOverlay(true);
2788 spyWindow->setSpy(true);
2789
2790 sp<FakeWindowHandle> leftWindow =
2791 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2792 leftWindow->setFrame(Rect(0, 0, 200, 200));
2793
2794 sp<FakeWindowHandle> rightWindow =
2795 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2796 rightWindow->setFrame(Rect(200, 0, 400, 200));
2797
2798 mDispatcher->onWindowInfosChanged(
2799 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2800
2801 const int32_t stylusDeviceId = 1;
2802 const int32_t touchDeviceId = 2;
2803
2804 // Stylus hover on the left window
2805 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2806 .deviceId(stylusDeviceId)
2807 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2808 .build());
2809 leftWindow->consumeMotionEvent(
2810 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2811 spyWindow->consumeMotionEvent(
2812 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2813
2814 // Touch down on the right window.
2815 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2816 .deviceId(touchDeviceId)
2817 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2818 .build());
2819 leftWindow->consumeMotionEvent(
2820 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2821 spyWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2823 spyWindow->consumeMotionEvent(
2824 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2825 rightWindow->consumeMotionEvent(
2826 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2827
2828 // Stylus movements continue, but are ignored because the touch is down.
2829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2830 .deviceId(stylusDeviceId)
2831 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2832 .build());
2833
2834 // Touch movements continue. They should be delivered to the right window and to the spy
2835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2836 .deviceId(touchDeviceId)
2837 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2838 .build());
2839 spyWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2841 rightWindow->consumeMotionEvent(
2842 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2843
2844 spyWindow->assertNoEvents();
2845 leftWindow->assertNoEvents();
2846 rightWindow->assertNoEvents();
2847}
2848
2849/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002850 * On a single window, use two different devices: mouse and touch.
2851 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2852 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2853 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2854 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2855 * represent a new gesture.
2856 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002857TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2859 sp<FakeWindowHandle> window =
2860 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2861 window->setFrame(Rect(0, 0, 400, 400));
2862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002863 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002864
2865 const int32_t touchDeviceId = 4;
2866 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002867
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002868 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002869 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2870 .deviceId(touchDeviceId)
2871 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2872 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002873 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002874 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2875 .deviceId(touchDeviceId)
2876 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2877 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002879 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002880 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2881 .deviceId(touchDeviceId)
2882 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2883 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2884 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002885 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2886 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2887 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2888
2889 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002890 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2891 .deviceId(mouseDeviceId)
2892 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2893 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2894 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002895
2896 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002897 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002898 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2899
Prabir Pradhan678438e2023-04-13 19:32:51 +00002900 mDispatcher->notifyMotion(
2901 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2902 .deviceId(mouseDeviceId)
2903 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2904 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2906 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002907 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2908
2909 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2911 .deviceId(touchDeviceId)
2912 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2913 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2914 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002915 // Since we already canceled this touch gesture, it will be ignored until a completely new
2916 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2917 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2918 // However, mouse movements should continue to work.
2919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2920 .deviceId(mouseDeviceId)
2921 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2923 .build());
2924 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2925
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002926 window->assertNoEvents();
2927}
2928
2929/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002930 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2931 * the injected event.
2932 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2935 sp<FakeWindowHandle> window =
2936 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2937 window->setFrame(Rect(0, 0, 400, 400));
2938
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002939 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002940
2941 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002942 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2943 // completion.
2944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002945 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002946 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2947 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002949 .build()));
2950 window->consumeMotionEvent(
2951 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2952
2953 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2954 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2956 .deviceId(touchDeviceId)
2957 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2958 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002959
2960 window->consumeMotionEvent(
2961 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2962 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2963}
2964
2965/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002966 * This test is similar to the test above, but the sequence of injected events is different.
2967 *
2968 * Two windows: a window on the left and a window on the right.
2969 * Mouse is hovered over the left window.
2970 * Next, we tap on the left window, where the cursor was last seen.
2971 *
2972 * After that, we inject one finger down onto the right window, and then a second finger down onto
2973 * the left window.
2974 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2975 * window (first), and then another on the left window (second).
2976 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2977 * In the buggy implementation, second finger down on the left window would cause a crash.
2978 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002979TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2981 sp<FakeWindowHandle> leftWindow =
2982 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2983 leftWindow->setFrame(Rect(0, 0, 200, 200));
2984
2985 sp<FakeWindowHandle> rightWindow =
2986 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2987 rightWindow->setFrame(Rect(200, 0, 400, 200));
2988
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002989 mDispatcher->onWindowInfosChanged(
2990 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002991
2992 const int32_t mouseDeviceId = 6;
2993 const int32_t touchDeviceId = 4;
2994 // Hover over the left window. Keep the cursor there.
2995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002996 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2998 AINPUT_SOURCE_MOUSE)
2999 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003000 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003001 .build()));
3002 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3003
3004 // Tap on left window
3005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003006 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003007 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3008 AINPUT_SOURCE_TOUCHSCREEN)
3009 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003010 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003011 .build()));
3012
3013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003014 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003015 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3016 AINPUT_SOURCE_TOUCHSCREEN)
3017 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003018 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003019 .build()));
3020 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3021 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3022 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3023
3024 // First finger down on right window
3025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003026 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003027 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3028 AINPUT_SOURCE_TOUCHSCREEN)
3029 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003030 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003031 .build()));
3032 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3033
3034 // Second finger down on the left window
3035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003036 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003037 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3038 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003039 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3040 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003041 .build()));
3042 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3043 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3044
3045 // No more events
3046 leftWindow->assertNoEvents();
3047 rightWindow->assertNoEvents();
3048}
3049
3050/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003051 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3052 * While the touch is down, new hover events from the stylus device should be ignored. After the
3053 * touch is gone, stylus hovering should start working again.
3054 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003055TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3057 sp<FakeWindowHandle> window =
3058 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3059 window->setFrame(Rect(0, 0, 200, 200));
3060
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003061 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003062
3063 const int32_t stylusDeviceId = 5;
3064 const int32_t touchDeviceId = 4;
3065 // Start hovering with stylus
3066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003067 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003069 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003070 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003071 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003072 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003073
3074 // Finger down on the window
3075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003076 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003077 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003078 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003079 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003080 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003081 window->consumeMotionEvent(
3082 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3083 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003084
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003085 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003086 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003087 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003088 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3089 AINPUT_SOURCE_STYLUS)
3090 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003091 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003092 .build()));
3093 // No event should be sent. This event should be ignored because a pointer from another device
3094 // is already down.
3095
3096 // Lift up the finger
3097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003098 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003099 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3100 AINPUT_SOURCE_TOUCHSCREEN)
3101 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003102 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003103 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003104 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003105
3106 // Now that the touch is gone, stylus hovering should start working again
3107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003108 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003109 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3110 AINPUT_SOURCE_STYLUS)
3111 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003112 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003113 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003114 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3115 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003116 window->assertNoEvents();
3117}
3118
3119/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120 * A spy window above a window with no input channel.
3121 * Start hovering with a stylus device, and then tap with it.
3122 * Ensure spy window receives the entire sequence.
3123 */
3124TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3125 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3126 sp<FakeWindowHandle> spyWindow =
3127 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3128 spyWindow->setFrame(Rect(0, 0, 200, 200));
3129 spyWindow->setTrustedOverlay(true);
3130 spyWindow->setSpy(true);
3131 sp<FakeWindowHandle> window =
3132 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3133 window->setNoInputChannel(true);
3134 window->setFrame(Rect(0, 0, 200, 200));
3135
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003136 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003137
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003138 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003139 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3140 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3141 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003142 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3143 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3145 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3146 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003147 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3148
3149 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003150 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3151 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3152 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003153 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3154
3155 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003156 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3157 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3158 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003159 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3160
3161 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3163 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3164 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003165 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3166 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003167 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3168 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3169 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003170 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3171
3172 // No more events
3173 spyWindow->assertNoEvents();
3174 window->assertNoEvents();
3175}
3176
3177/**
3178 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3179 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3180 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3181 * While the mouse is down, new move events from the touch device should be ignored.
3182 */
3183TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3184 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3185 sp<FakeWindowHandle> spyWindow =
3186 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3187 spyWindow->setFrame(Rect(0, 0, 200, 200));
3188 spyWindow->setTrustedOverlay(true);
3189 spyWindow->setSpy(true);
3190 sp<FakeWindowHandle> window =
3191 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3192 window->setFrame(Rect(0, 0, 200, 200));
3193
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003194 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003195
3196 const int32_t mouseDeviceId = 7;
3197 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003198
3199 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003200 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3201 .deviceId(mouseDeviceId)
3202 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3203 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003204 spyWindow->consumeMotionEvent(
3205 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3206 window->consumeMotionEvent(
3207 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3208
3209 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3211 .deviceId(touchDeviceId)
3212 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3213 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003214 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3215 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3216 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3217 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3218
Prabir Pradhan678438e2023-04-13 19:32:51 +00003219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3220 .deviceId(touchDeviceId)
3221 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3222 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003223 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3224 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3225
3226 // Pilfer the stream
3227 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3228 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3229
Prabir Pradhan678438e2023-04-13 19:32:51 +00003230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3231 .deviceId(touchDeviceId)
3232 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3233 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003234 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3235
3236 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003237 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3238 .deviceId(mouseDeviceId)
3239 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3240 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3241 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003242
3243 spyWindow->consumeMotionEvent(
3244 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3245 spyWindow->consumeMotionEvent(
3246 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3247 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3248
Prabir Pradhan678438e2023-04-13 19:32:51 +00003249 mDispatcher->notifyMotion(
3250 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3251 .deviceId(mouseDeviceId)
3252 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3253 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3254 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3255 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003256 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3257 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3258
3259 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3261 .deviceId(mouseDeviceId)
3262 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3263 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3264 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003265 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3266 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3267
3268 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003269 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
3271 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3272 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003273
3274 // No more events
3275 spyWindow->assertNoEvents();
3276 window->assertNoEvents();
3277}
3278
3279/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003280 * On the display, have a single window, and also an area where there's no window.
3281 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3282 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3283 */
3284TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3286 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003287 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003288
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003289 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003290
3291 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003292 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003293
3294 mDispatcher->waitForIdle();
3295 window->assertNoEvents();
3296
3297 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003298 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003299 mDispatcher->waitForIdle();
3300 window->consumeMotionDown();
3301}
3302
3303/**
3304 * Same test as above, but instead of touching the empty space, the first touch goes to
3305 * non-touchable window.
3306 */
3307TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3309 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003310 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003311 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3312 window1->setTouchable(false);
3313 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003314 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003315 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3316
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003317 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003318
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003319 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003320 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003321
3322 mDispatcher->waitForIdle();
3323 window1->assertNoEvents();
3324 window2->assertNoEvents();
3325
3326 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003327 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003328 mDispatcher->waitForIdle();
3329 window2->consumeMotionDown();
3330}
3331
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003332/**
3333 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3334 * to the event time of the first ACTION_DOWN sent to the particular window.
3335 */
3336TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3337 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3338 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003339 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003340 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3341 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003342 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003343 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3344
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003345 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003346
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003347 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003348 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003349
3350 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351
3352 MotionEvent* motionEvent1 = window1->consumeMotion();
3353 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003354 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3356 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003357
3358 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003359 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003360 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003361 MotionEvent* motionEvent2 = window2->consumeMotion();
3362 ASSERT_NE(motionEvent2, nullptr);
3363 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003364 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003365 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003366
3367 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003368 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003369 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003370 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003371
3372 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003373 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003374 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003375 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003376
3377 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3378 window1->consumeMotionMove();
3379 window1->assertNoEvents();
3380
3381 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003382 mDispatcher->notifyMotion(
3383 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003384 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003385 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003386
Prabir Pradhan678438e2023-04-13 19:32:51 +00003387 mDispatcher->notifyMotion(
3388 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003389 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003390 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003391}
3392
Garfield Tandf26e862020-07-01 20:18:19 -07003393TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003395 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003396 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003397 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003398 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003399 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003400 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003401
3402 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3403
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003404 mDispatcher->onWindowInfosChanged(
3405 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003406
3407 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003409 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003410 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3411 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003412 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003413 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003414 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003415
3416 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003418 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003419 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3420 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003421 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003422 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003423 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3424 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003425
3426 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003428 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003429 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3430 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003431 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003432 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003433 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3434 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003435
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003437 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003438 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3439 AINPUT_SOURCE_MOUSE)
3440 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3441 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003442 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003443 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003444 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003445
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003447 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003448 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3449 AINPUT_SOURCE_MOUSE)
3450 .buttonState(0)
3451 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003452 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003453 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003454 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003455
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003457 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003458 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3459 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003460 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003461 .build()));
3462 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3463
3464 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003466 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003467 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3468 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003469 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003470 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003471 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003472
3473 // No more events
3474 windowLeft->assertNoEvents();
3475 windowRight->assertNoEvents();
3476}
3477
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003478/**
3479 * Put two fingers down (and don't release them) and click the mouse button.
3480 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3481 * currently active gesture should be canceled, and the new one should proceed.
3482 */
3483TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3485 sp<FakeWindowHandle> window =
3486 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3487 window->setFrame(Rect(0, 0, 600, 800));
3488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003490
3491 const int32_t touchDeviceId = 4;
3492 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003493
3494 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003495 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3496 .deviceId(touchDeviceId)
3497 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3498 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003499
Prabir Pradhan678438e2023-04-13 19:32:51 +00003500 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3501 .deviceId(touchDeviceId)
3502 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3503 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3504 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003505 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3506 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3507
3508 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3510 .deviceId(mouseDeviceId)
3511 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3512 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3513 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003514 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3515 WithPointerCount(2u)));
3516 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3517
Prabir Pradhan678438e2023-04-13 19:32:51 +00003518 mDispatcher->notifyMotion(
3519 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3520 .deviceId(mouseDeviceId)
3521 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3522 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3523 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3524 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003525 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3526
3527 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3528 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3530 .deviceId(touchDeviceId)
3531 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3532 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3533 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003534 window->assertNoEvents();
3535}
3536
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003537TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3538 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3539
3540 sp<FakeWindowHandle> spyWindow =
3541 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3542 spyWindow->setFrame(Rect(0, 0, 600, 800));
3543 spyWindow->setTrustedOverlay(true);
3544 spyWindow->setSpy(true);
3545 sp<FakeWindowHandle> window =
3546 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3547 window->setFrame(Rect(0, 0, 600, 800));
3548
3549 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003550 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003551
3552 // Send mouse cursor to the window
3553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003554 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003555 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3556 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003557 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003558 .build()));
3559
3560 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3561 WithSource(AINPUT_SOURCE_MOUSE)));
3562 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3563 WithSource(AINPUT_SOURCE_MOUSE)));
3564
3565 window->assertNoEvents();
3566 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003567}
3568
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003569TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3571
3572 sp<FakeWindowHandle> spyWindow =
3573 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3574 spyWindow->setFrame(Rect(0, 0, 600, 800));
3575 spyWindow->setTrustedOverlay(true);
3576 spyWindow->setSpy(true);
3577 sp<FakeWindowHandle> window =
3578 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3579 window->setFrame(Rect(0, 0, 600, 800));
3580
3581 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003582 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003583
3584 // Send mouse cursor to the window
3585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003586 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003587 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3588 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003589 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003590 .build()));
3591
3592 // Move mouse cursor
3593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003594 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003595 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3596 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003597 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003598 .build()));
3599
3600 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3601 WithSource(AINPUT_SOURCE_MOUSE)));
3602 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3603 WithSource(AINPUT_SOURCE_MOUSE)));
3604 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3605 WithSource(AINPUT_SOURCE_MOUSE)));
3606 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3607 WithSource(AINPUT_SOURCE_MOUSE)));
3608 // Touch down on the window
3609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003610 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003611 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3612 AINPUT_SOURCE_TOUCHSCREEN)
3613 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003614 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003615 .build()));
3616 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3617 WithSource(AINPUT_SOURCE_MOUSE)));
3618 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3619 WithSource(AINPUT_SOURCE_MOUSE)));
3620 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3621 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3622 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3623 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3624
3625 // pilfer the motion, retaining the gesture on the spy window.
3626 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3627 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3628 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3629
3630 // Touch UP on the window
3631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003632 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003633 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3634 AINPUT_SOURCE_TOUCHSCREEN)
3635 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003636 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003637 .build()));
3638 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3639 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3640
3641 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3642 // to send a new gesture. It should again go to both windows (spy and the window below), just
3643 // like the first gesture did, before pilfering. The window configuration has not changed.
3644
3645 // One more tap - DOWN
3646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003647 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003648 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3649 AINPUT_SOURCE_TOUCHSCREEN)
3650 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003651 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003652 .build()));
3653 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3654 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3655 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3656 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3657
3658 // Touch UP on the window
3659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003660 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003661 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3662 AINPUT_SOURCE_TOUCHSCREEN)
3663 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003664 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003665 .build()));
3666 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3667 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3668 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3669 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3670
3671 window->assertNoEvents();
3672 spyWindow->assertNoEvents();
3673}
3674
Garfield Tandf26e862020-07-01 20:18:19 -07003675// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3676// directly in this test.
3677TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003678 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003679 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003680 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003681 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003682
3683 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3684
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003685 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003686
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003688 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003689 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3690 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003691 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003692 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003693 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003694 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003696 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003697 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3698 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003699 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003700 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003701 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3702 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003703
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003705 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003706 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3707 AINPUT_SOURCE_MOUSE)
3708 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3709 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003710 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003711 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003712 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003713
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003715 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003716 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3717 AINPUT_SOURCE_MOUSE)
3718 .buttonState(0)
3719 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003721 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003722 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003723
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003725 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003726 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3727 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003729 .build()));
3730 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3731
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003732 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3733 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3734 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003735 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003736 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3737 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003739 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003740 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003741}
3742
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003743/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003744 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3745 * is generated.
3746 */
3747TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3749 sp<FakeWindowHandle> window =
3750 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3751 window->setFrame(Rect(0, 0, 1200, 800));
3752
3753 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003756
3757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003758 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003759 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3760 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003761 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003762 .build()));
3763 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3764
3765 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003766 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003767 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3768}
3769
3770/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003771 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3772 */
3773TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3775 sp<FakeWindowHandle> window =
3776 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3777 window->setFrame(Rect(0, 0, 1200, 800));
3778
3779 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3780
3781 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3782
3783 MotionEventBuilder hoverEnterBuilder =
3784 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3785 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3786 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3788 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3790 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3791 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3792 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3793}
3794
3795/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003796 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3797 */
3798TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3800 sp<FakeWindowHandle> window =
3801 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3802 window->setFrame(Rect(0, 0, 100, 100));
3803
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003804 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003805
3806 const int32_t mouseDeviceId = 7;
3807 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003808
3809 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3811 .deviceId(mouseDeviceId)
3812 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3813 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003814 window->consumeMotionEvent(
3815 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3816
3817 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3819 .deviceId(touchDeviceId)
3820 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3821 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003822
3823 window->consumeMotionEvent(
3824 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3825 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3826}
3827
3828/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003829 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003830 * The tap causes a HOVER_EXIT event to be generated because the current event
3831 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003832 */
3833TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3835 sp<FakeWindowHandle> window =
3836 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3837 window->setFrame(Rect(0, 0, 100, 100));
3838
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003839 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3842 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003843 ASSERT_NO_FATAL_FAILURE(
3844 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3845 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003846
3847 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003848 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3849 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3850 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003851 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003852 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3853 WithSource(AINPUT_SOURCE_MOUSE))));
3854
3855 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003856 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3857 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3858
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3860 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3861 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003862 ASSERT_NO_FATAL_FAILURE(
3863 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3864 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3865}
3866
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003867TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3869 sp<FakeWindowHandle> windowDefaultDisplay =
3870 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3871 ADISPLAY_ID_DEFAULT);
3872 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3873 sp<FakeWindowHandle> windowSecondDisplay =
3874 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3875 SECOND_DISPLAY_ID);
3876 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3877
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003878 mDispatcher->onWindowInfosChanged(
3879 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003880
3881 // Set cursor position in window in default display and check that hover enter and move
3882 // events are generated.
3883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003884 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003885 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3886 AINPUT_SOURCE_MOUSE)
3887 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003888 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003889 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003890 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003891
3892 // Remove all windows in secondary display and check that no event happens on window in
3893 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003894 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3895
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003896 windowDefaultDisplay->assertNoEvents();
3897
3898 // Move cursor position in window in default display and check that only hover move
3899 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003900 mDispatcher->onWindowInfosChanged(
3901 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003903 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003904 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3905 AINPUT_SOURCE_MOUSE)
3906 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003907 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003908 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003909 windowDefaultDisplay->consumeMotionEvent(
3910 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3911 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003912 windowDefaultDisplay->assertNoEvents();
3913}
3914
Garfield Tan00f511d2019-06-12 16:55:40 -07003915TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003917
3918 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003919 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003920 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003921 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003922 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003923 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003924
3925 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3926
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003927 mDispatcher->onWindowInfosChanged(
3928 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003929
3930 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3931 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003933 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003934 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003935 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003936 windowRight->assertNoEvents();
3937}
3938
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003939TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003941 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3942 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003943 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003944
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003945 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003946 setFocusedWindow(window);
3947
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003948 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003949
Prabir Pradhan678438e2023-04-13 19:32:51 +00003950 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003951
3952 // Window should receive key down event.
3953 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3954
3955 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3956 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003957 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003958 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003959 AKEY_EVENT_FLAG_CANCELED);
3960}
3961
3962TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003963 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003964 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3965 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003966
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003968
Prabir Pradhan678438e2023-04-13 19:32:51 +00003969 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3970 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003971
3972 // Window should receive motion down event.
3973 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3974
3975 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3976 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003977 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003978 window->consumeMotionEvent(
3979 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003980}
3981
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003982TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3984 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3985 "Fake Window", ADISPLAY_ID_DEFAULT);
3986
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003987 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003988
3989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3990 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3991 .build());
3992
3993 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3994
3995 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3996 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3997 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3998
3999 // After the device has been reset, a new hovering stream can be sent to the window
4000 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4001 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4002 .build());
4003 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4004}
4005
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004006TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004008 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4009 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004010 window->setFocusable(true);
4011
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004012 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004013 setFocusedWindow(window);
4014
4015 window->consumeFocusEvent(true);
4016
Prabir Pradhan678438e2023-04-13 19:32:51 +00004017 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004018 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4019 const nsecs_t injectTime = keyArgs.eventTime;
4020 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004021 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004022 // The dispatching time should be always greater than or equal to intercept key timeout.
4023 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4024 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4025 std::chrono::nanoseconds(interceptKeyTimeout).count());
4026}
4027
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004028/**
4029 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4030 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004031TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004033 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4034 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004035 window->setFocusable(true);
4036
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004037 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004038 setFocusedWindow(window);
4039
4040 window->consumeFocusEvent(true);
4041
Prabir Pradhan678438e2023-04-13 19:32:51 +00004042 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004043 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004044
4045 // Set a value that's significantly larger than the default consumption timeout. If the
4046 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4047 mFakePolicy->setInterceptKeyTimeout(600ms);
4048 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4049 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004050 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4051}
4052
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004053/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004054 * Two windows. First is a regular window. Second does not overlap with the first, and has
4055 * WATCH_OUTSIDE_TOUCH.
4056 * Both windows are owned by the same UID.
4057 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4058 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4059 */
4060TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4061 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004062 sp<FakeWindowHandle> window =
4063 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004064 window->setFrame(Rect{0, 0, 100, 100});
4065
4066 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004067 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004068 ADISPLAY_ID_DEFAULT);
4069 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4070 outsideWindow->setWatchOutsideTouch(true);
4071 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004072 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004073
4074 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004075 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4076 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4077 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004078 window->consumeMotionDown();
4079 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4080 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4081 outsideWindow->consumeMotionEvent(
4082 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4083}
4084
4085/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004086 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4087 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4088 * ACTION_OUTSIDE event is sent per gesture.
4089 */
4090TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4091 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004093 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4094 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004095 window->setWatchOutsideTouch(true);
4096 window->setFrame(Rect{0, 0, 100, 100});
4097 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004098 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4099 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004100 secondWindow->setFrame(Rect{100, 100, 200, 200});
4101 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004102 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4103 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004104 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004105 mDispatcher->onWindowInfosChanged(
4106 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004107
4108 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004109 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4110 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4111 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004112 window->assertNoEvents();
4113 secondWindow->assertNoEvents();
4114
4115 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4116 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004117 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4118 ADISPLAY_ID_DEFAULT,
4119 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004120 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4121 window->consumeMotionEvent(
4122 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004123 secondWindow->consumeMotionDown();
4124 thirdWindow->assertNoEvents();
4125
4126 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4127 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004128 mDispatcher->notifyMotion(
4129 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4130 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004131 window->assertNoEvents();
4132 secondWindow->consumeMotionMove();
4133 thirdWindow->consumeMotionDown();
4134}
4135
Prabir Pradhan814fe082022-07-22 20:22:18 +00004136TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004138 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4139 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004140 window->setFocusable(true);
4141
Patrick Williamsd828f302023-04-28 17:52:08 -05004142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004143 setFocusedWindow(window);
4144
4145 window->consumeFocusEvent(true);
4146
Prabir Pradhan678438e2023-04-13 19:32:51 +00004147 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4148 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4149 mDispatcher->notifyKey(keyDown);
4150 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004151
4152 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4153 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4154
4155 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004156 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004157
4158 window->consumeFocusEvent(false);
4159
Prabir Pradhan678438e2023-04-13 19:32:51 +00004160 mDispatcher->notifyKey(keyDown);
4161 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004162 window->assertNoEvents();
4163}
4164
Arthur Hung96483742022-11-15 03:30:48 +00004165TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4167 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4168 "Fake Window", ADISPLAY_ID_DEFAULT);
4169 // Ensure window is non-split and have some transform.
4170 window->setPreventSplitting(true);
4171 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004172 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004173
4174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004175 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004176 {50, 50}))
4177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4178 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4179
4180 const MotionEvent secondFingerDownEvent =
4181 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4182 .displayId(ADISPLAY_ID_DEFAULT)
4183 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004184 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4185 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004186 .build();
4187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004188 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004189 InputEventInjectionSync::WAIT_FOR_RESULT))
4190 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4191
4192 const MotionEvent* event = window->consumeMotion();
4193 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4194 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4195 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4196 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4197 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4198}
4199
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004200/**
4201 * Two windows: a splittable and a non-splittable.
4202 * The non-splittable window shouldn't receive any "incomplete" gestures.
4203 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4204 * The second pointer should be dropped because the initial window is splittable, so it won't get
4205 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4206 * "incomplete" gestures.
4207 */
4208TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4209 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4210 sp<FakeWindowHandle> leftWindow =
4211 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4212 ADISPLAY_ID_DEFAULT);
4213 leftWindow->setPreventSplitting(false);
4214 leftWindow->setFrame(Rect(0, 0, 100, 100));
4215 sp<FakeWindowHandle> rightWindow =
4216 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4217 ADISPLAY_ID_DEFAULT);
4218 rightWindow->setPreventSplitting(true);
4219 rightWindow->setFrame(Rect(100, 100, 200, 200));
4220 mDispatcher->onWindowInfosChanged(
4221 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4222
4223 // Touch down on left, splittable window
4224 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4225 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4226 .build());
4227 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4228
4229 mDispatcher->notifyMotion(
4230 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4231 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4232 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4233 .build());
4234 leftWindow->assertNoEvents();
4235 rightWindow->assertNoEvents();
4236}
4237
Harry Cuttsb166c002023-05-09 13:06:05 +00004238TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4239 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4240 sp<FakeWindowHandle> window =
4241 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4242 window->setFrame(Rect(0, 0, 400, 400));
4243 sp<FakeWindowHandle> trustedOverlay =
4244 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4245 ADISPLAY_ID_DEFAULT);
4246 trustedOverlay->setSpy(true);
4247 trustedOverlay->setTrustedOverlay(true);
4248
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004249 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004250
4251 // Start a three-finger touchpad swipe
4252 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4253 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4254 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4255 .build());
4256 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4257 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4258 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4259 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4260 .build());
4261 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4262 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4263 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4264 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4265 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4266 .build());
4267
4268 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4269 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4270 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4271
4272 // Move the swipe a bit
4273 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4274 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4275 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4276 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4277 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4278 .build());
4279
4280 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4281
4282 // End the swipe
4283 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4284 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4285 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4286 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4287 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4288 .build());
4289 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4290 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4291 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4292 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4293 .build());
4294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4295 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4296 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4297 .build());
4298
4299 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4300 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4301 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4302
4303 window->assertNoEvents();
4304}
4305
4306TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4308 sp<FakeWindowHandle> window =
4309 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4310 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004311 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004312
4313 // Start a three-finger touchpad swipe
4314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4315 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4316 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4317 .build());
4318 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4319 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4320 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4321 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4322 .build());
4323 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4324 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4325 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4326 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4327 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4328 .build());
4329
4330 // Move the swipe a bit
4331 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4332 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4333 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4334 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4335 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4336 .build());
4337
4338 // End the swipe
4339 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4340 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4341 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4342 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4343 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4344 .build());
4345 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4346 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4347 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4348 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4349 .build());
4350 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4351 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4352 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4353 .build());
4354
4355 window->assertNoEvents();
4356}
4357
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004358/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004359 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4360 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004361 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004362 */
4363TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4365 sp<FakeWindowHandle> window =
4366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4367 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004369
4370 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4372 .downTime(baseTime + 10)
4373 .eventTime(baseTime + 10)
4374 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4375 .build());
4376
4377 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4378
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004379 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004380 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004381
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004382 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004383
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004384 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4385 .downTime(baseTime + 10)
4386 .eventTime(baseTime + 30)
4387 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4388 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4389 .build());
4390
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004391 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4392
4393 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004394 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4395 .downTime(baseTime + 10)
4396 .eventTime(baseTime + 40)
4397 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4398 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4399 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004400
4401 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4402
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4404 .downTime(baseTime + 10)
4405 .eventTime(baseTime + 50)
4406 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4407 .build());
4408
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004409 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4410
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4412 .downTime(baseTime + 60)
4413 .eventTime(baseTime + 60)
4414 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4415 .build());
4416
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004417 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004418}
4419
4420/**
Hu Guo771a7692023-09-17 20:51:08 +08004421 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4422 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4423 * its coordinates should be converted by the transform of the windows of target screen.
4424 */
4425TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4426 // This case will create a window and a spy window on the default display and mirror
4427 // window on the second display. cancel event is sent through spy window pilferPointers
4428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4429
4430 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4431 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4432 spyWindowDefaultDisplay->setTrustedOverlay(true);
4433 spyWindowDefaultDisplay->setSpy(true);
4434
4435 sp<FakeWindowHandle> windowDefaultDisplay =
4436 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4437 ADISPLAY_ID_DEFAULT);
4438 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4439
4440 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4441 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4442
4443 // Add the windows to the dispatcher
4444 mDispatcher->onWindowInfosChanged(
4445 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4446 *windowSecondDisplay->getInfo()},
4447 {},
4448 0,
4449 0});
4450
4451 // Send down to ADISPLAY_ID_DEFAULT
4452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4453 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4454 {100, 100}))
4455 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4456
4457 spyWindowDefaultDisplay->consumeMotionDown();
4458 windowDefaultDisplay->consumeMotionDown();
4459
4460 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4461
4462 // windowDefaultDisplay gets cancel
4463 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4464 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4465
4466 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4467 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4468 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4469 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4470 EXPECT_EQ(100, event->getX(0));
4471 EXPECT_EQ(100, event->getY(0));
4472}
4473
4474/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004475 * Ensure the correct coordinate spaces are used by InputDispatcher.
4476 *
4477 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4478 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4479 * space.
4480 */
4481class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4482public:
4483 void SetUp() override {
4484 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004485 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004486 }
4487
4488 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4489 gui::DisplayInfo info;
4490 info.displayId = displayId;
4491 info.transform = transform;
4492 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004493 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004494 }
4495
4496 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4497 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004498 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004499 }
4500
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004501 void removeAllWindowsAndDisplays() {
4502 mDisplayInfos.clear();
4503 mWindowInfos.clear();
4504 }
4505
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004506 // Set up a test scenario where the display has a scaled projection and there are two windows
4507 // on the display.
4508 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4509 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4510 // respectively.
4511 ui::Transform displayTransform;
4512 displayTransform.set(2, 0, 0, 4);
4513 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4514
4515 std::shared_ptr<FakeApplicationHandle> application =
4516 std::make_shared<FakeApplicationHandle>();
4517
4518 // Add two windows to the display. Their frames are represented in the display space.
4519 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004520 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4521 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004522 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4523 addWindow(firstWindow);
4524
4525 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004526 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4527 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004528 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4529 addWindow(secondWindow);
4530 return {std::move(firstWindow), std::move(secondWindow)};
4531 }
4532
4533private:
4534 std::vector<gui::DisplayInfo> mDisplayInfos;
4535 std::vector<gui::WindowInfo> mWindowInfos;
4536};
4537
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004538TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004539 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4540 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004541 // selected so that if the hit test was performed with the point and the bounds being in
4542 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004543 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4544 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4545 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004546
4547 firstWindow->consumeMotionDown();
4548 secondWindow->assertNoEvents();
4549}
4550
4551// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4552// the event should be treated as being in the logical display space.
4553TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4554 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4555 // Send down to the first window. The point is represented in the logical display space. The
4556 // point is selected so that if the hit test was done in logical display space, then it would
4557 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004558 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004559 PointF{75 * 2, 55 * 4});
4560
4561 firstWindow->consumeMotionDown();
4562 secondWindow->assertNoEvents();
4563}
4564
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004565// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4566// event should be treated as being in the logical display space.
4567TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4568 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4569
4570 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4571 ui::Transform injectedEventTransform;
4572 injectedEventTransform.set(matrix);
4573 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4574 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4575
4576 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4577 .displayId(ADISPLAY_ID_DEFAULT)
4578 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004579 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004580 .x(untransformedPoint.x)
4581 .y(untransformedPoint.y))
4582 .build();
4583 event.transform(matrix);
4584
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004585 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004586 InputEventInjectionSync::WAIT_FOR_RESULT);
4587
4588 firstWindow->consumeMotionDown();
4589 secondWindow->assertNoEvents();
4590}
4591
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004592TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4593 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4594
4595 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004596 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4597 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4598 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004599
4600 firstWindow->assertNoEvents();
4601 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004602 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004603 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4604
4605 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4606 EXPECT_EQ(300, event->getRawX(0));
4607 EXPECT_EQ(880, event->getRawY(0));
4608
4609 // Ensure that the x and y values are in the window's coordinate space.
4610 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4611 // the logical display space. This will be the origin of the window space.
4612 EXPECT_EQ(100, event->getX(0));
4613 EXPECT_EQ(80, event->getY(0));
4614}
4615
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004616TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4617 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4618 // The monitor will always receive events in the logical display's coordinate space, because
4619 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004620 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004621
4622 // Send down to the first window.
4623 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4624 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4625 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4626 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4627
4628 // Second pointer goes down on second window.
4629 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4630 ADISPLAY_ID_DEFAULT,
4631 {PointF{50, 100}, PointF{150, 220}}));
4632 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4633 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4634 {1, PointF{300, 880}}};
4635 monitor.consumeMotionEvent(
4636 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4637
4638 mDispatcher->cancelCurrentTouch();
4639
4640 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4641 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4642 monitor.consumeMotionEvent(
4643 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4644}
4645
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004646TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4647 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4648
4649 // Send down to the first window.
4650 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4651 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4652 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4653
4654 // The pointer is transferred to the second window, and the second window receives it in the
4655 // correct coordinate space.
4656 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4657 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4658 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4659}
4660
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004661TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4662 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4663
4664 // Send hover move to the second window, and ensure it shows up as hover enter.
4665 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4666 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4667 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4668 WithCoords(100, 80), WithRawCoords(300, 880)));
4669
4670 // Touch down at the same location and ensure a hover exit is synthesized.
4671 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4672 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4673 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4674 WithRawCoords(300, 880)));
4675 secondWindow->consumeMotionEvent(
4676 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4677 secondWindow->assertNoEvents();
4678 firstWindow->assertNoEvents();
4679}
4680
4681TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4682 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4683
4684 // Send hover enter to second window
4685 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4686 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4687 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4688 WithCoords(100, 80), WithRawCoords(300, 880)));
4689
4690 mDispatcher->cancelCurrentTouch();
4691
4692 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4693 WithRawCoords(300, 880)));
4694 secondWindow->assertNoEvents();
4695 firstWindow->assertNoEvents();
4696}
4697
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004698/** Ensure consistent behavior of InputDispatcher in all orientations. */
4699class InputDispatcherDisplayOrientationFixture
4700 : public InputDispatcherDisplayProjectionTest,
4701 public ::testing::WithParamInterface<ui::Rotation> {};
4702
4703// This test verifies the touchable region of a window for all rotations of the display by tapping
4704// in different locations on the display, specifically points close to the four corners of a
4705// window.
4706TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4707 constexpr static int32_t displayWidth = 400;
4708 constexpr static int32_t displayHeight = 800;
4709
4710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4711
4712 const auto rotation = GetParam();
4713
4714 // Set up the display with the specified rotation.
4715 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4716 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4717 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4718 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4719 logicalDisplayWidth, logicalDisplayHeight);
4720 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4721
4722 // Create a window with its bounds determined in the logical display.
4723 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4724 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4725 sp<FakeWindowHandle> window =
4726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4727 window->setFrame(frameInDisplay, displayTransform);
4728 addWindow(window);
4729
4730 // The following points in logical display space should be inside the window.
4731 static const std::array<vec2, 4> insidePoints{
4732 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4733 for (const auto pointInsideWindow : insidePoints) {
4734 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4735 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004736 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4737 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4738 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004739 window->consumeMotionDown();
4740
Prabir Pradhan678438e2023-04-13 19:32:51 +00004741 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4742 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4743 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004744 window->consumeMotionUp();
4745 }
4746
4747 // The following points in logical display space should be outside the window.
4748 static const std::array<vec2, 5> outsidePoints{
4749 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4750 for (const auto pointOutsideWindow : outsidePoints) {
4751 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4752 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004753 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4754 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4755 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004756
Prabir Pradhan678438e2023-04-13 19:32:51 +00004757 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4758 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4759 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004760 }
4761 window->assertNoEvents();
4762}
4763
4764// Run the precision tests for all rotations.
4765INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4766 InputDispatcherDisplayOrientationFixture,
4767 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4768 ui::ROTATION_270),
4769 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4770 return ftl::enum_string(testParamInfo.param);
4771 });
4772
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004773using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4774 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004775
4776class TransferTouchFixture : public InputDispatcherTest,
4777 public ::testing::WithParamInterface<TransferFunction> {};
4778
4779TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004781
4782 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004783 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004784 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4785 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004786 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004787 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004788 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4789 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004790 sp<FakeWindowHandle> wallpaper =
4791 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4792 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004793 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004794 mDispatcher->onWindowInfosChanged(
4795 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004796
4797 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004798 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4799 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004800
Svet Ganov5d3bc372020-01-26 23:11:07 -08004801 // Only the first window should get the down event
4802 firstWindow->consumeMotionDown();
4803 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004804 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004805
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004806 // Transfer touch to the second window
4807 TransferFunction f = GetParam();
4808 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4809 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004810 // The first window gets cancel and the second gets down
4811 firstWindow->consumeMotionCancel();
4812 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004813 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004814
4815 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004816 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4817 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004818 // The first window gets no events and the second gets up
4819 firstWindow->assertNoEvents();
4820 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004821 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004822}
4823
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004824/**
4825 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4826 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4827 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4828 * natural to the user.
4829 * In this test, we are sending a pointer to both spy window and first window. We then try to
4830 * transfer touch to the second window. The dispatcher should identify the first window as the
4831 * one that should lose the gesture, and therefore the action should be to move the gesture from
4832 * the first window to the second.
4833 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4834 * the other API, as well.
4835 */
4836TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4837 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4838
4839 // Create a couple of windows + a spy window
4840 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004841 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004842 spyWindow->setTrustedOverlay(true);
4843 spyWindow->setSpy(true);
4844 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004845 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004846 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004847 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004848
4849 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004850 mDispatcher->onWindowInfosChanged(
4851 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004852
4853 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004854 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4855 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004856 // Only the first window and spy should get the down event
4857 spyWindow->consumeMotionDown();
4858 firstWindow->consumeMotionDown();
4859
4860 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4861 // if f === 'transferTouch'.
4862 TransferFunction f = GetParam();
4863 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4864 ASSERT_TRUE(success);
4865 // The first window gets cancel and the second gets down
4866 firstWindow->consumeMotionCancel();
4867 secondWindow->consumeMotionDown();
4868
4869 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004870 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4871 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004872 // The first window gets no events and the second+spy get up
4873 firstWindow->assertNoEvents();
4874 spyWindow->consumeMotionUp();
4875 secondWindow->consumeMotionUp();
4876}
4877
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004878TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004880
4881 PointF touchPoint = {10, 10};
4882
4883 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004884 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004885 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4886 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004887 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004888 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004889 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4890 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004891 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004892
4893 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004894 mDispatcher->onWindowInfosChanged(
4895 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004896
4897 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004898 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4899 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4900 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004901 // Only the first window should get the down event
4902 firstWindow->consumeMotionDown();
4903 secondWindow->assertNoEvents();
4904
4905 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004906 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4907 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004908 // Only the first window should get the pointer down event
4909 firstWindow->consumeMotionPointerDown(1);
4910 secondWindow->assertNoEvents();
4911
4912 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004913 TransferFunction f = GetParam();
4914 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4915 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004916 // The first window gets cancel and the second gets down and pointer down
4917 firstWindow->consumeMotionCancel();
4918 secondWindow->consumeMotionDown();
4919 secondWindow->consumeMotionPointerDown(1);
4920
4921 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004922 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4923 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004924 // The first window gets nothing and the second gets pointer up
4925 firstWindow->assertNoEvents();
4926 secondWindow->consumeMotionPointerUp(1);
4927
4928 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004929 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4930 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004931 // The first window gets nothing and the second gets up
4932 firstWindow->assertNoEvents();
4933 secondWindow->consumeMotionUp();
4934}
4935
Arthur Hungc539dbb2022-12-08 07:45:36 +00004936TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4938
4939 // Create a couple of windows
4940 sp<FakeWindowHandle> firstWindow =
4941 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4942 ADISPLAY_ID_DEFAULT);
4943 firstWindow->setDupTouchToWallpaper(true);
4944 sp<FakeWindowHandle> secondWindow =
4945 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4946 ADISPLAY_ID_DEFAULT);
4947 secondWindow->setDupTouchToWallpaper(true);
4948
4949 sp<FakeWindowHandle> wallpaper1 =
4950 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4951 wallpaper1->setIsWallpaper(true);
4952
4953 sp<FakeWindowHandle> wallpaper2 =
4954 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4955 wallpaper2->setIsWallpaper(true);
4956 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004957 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4958 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4959 {},
4960 0,
4961 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004962
4963 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004964 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4965 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004966
4967 // Only the first window should get the down event
4968 firstWindow->consumeMotionDown();
4969 secondWindow->assertNoEvents();
4970 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4971 wallpaper2->assertNoEvents();
4972
4973 // Transfer touch focus to the second window
4974 TransferFunction f = GetParam();
4975 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4976 ASSERT_TRUE(success);
4977
4978 // The first window gets cancel and the second gets down
4979 firstWindow->consumeMotionCancel();
4980 secondWindow->consumeMotionDown();
4981 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4982 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4983
4984 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004985 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4986 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004987 // The first window gets no events and the second gets up
4988 firstWindow->assertNoEvents();
4989 secondWindow->consumeMotionUp();
4990 wallpaper1->assertNoEvents();
4991 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4992}
4993
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004994// For the cases of single pointer touch and two pointers non-split touch, the api's
4995// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4996// for the case where there are multiple pointers split across several windows.
4997INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4998 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004999 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5000 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005001 return dispatcher->transferTouch(destChannelToken,
5002 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005003 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005004 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5005 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005006 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005007 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005008 }));
5009
Svet Ganov5d3bc372020-01-26 23:11:07 -08005010TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005012
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005013 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005014 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5015 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005016 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005017
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005018 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005019 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5020 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005021 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005022
5023 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005024 mDispatcher->onWindowInfosChanged(
5025 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005026
5027 PointF pointInFirst = {300, 200};
5028 PointF pointInSecond = {300, 600};
5029
5030 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005031 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5032 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5033 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005034 // Only the first window should get the down event
5035 firstWindow->consumeMotionDown();
5036 secondWindow->assertNoEvents();
5037
5038 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005039 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5040 ADISPLAY_ID_DEFAULT,
5041 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005042 // The first window gets a move and the second a down
5043 firstWindow->consumeMotionMove();
5044 secondWindow->consumeMotionDown();
5045
5046 // Transfer touch focus to the second window
5047 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5048 // The first window gets cancel and the new gets pointer down (it already saw down)
5049 firstWindow->consumeMotionCancel();
5050 secondWindow->consumeMotionPointerDown(1);
5051
5052 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005053 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5054 ADISPLAY_ID_DEFAULT,
5055 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005056 // The first window gets nothing and the second gets pointer up
5057 firstWindow->assertNoEvents();
5058 secondWindow->consumeMotionPointerUp(1);
5059
5060 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005061 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5062 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005063 // The first window gets nothing and the second gets up
5064 firstWindow->assertNoEvents();
5065 secondWindow->consumeMotionUp();
5066}
5067
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005068// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5069// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5070// touch is not supported, so the touch should continue on those windows and the transferred-to
5071// window should get nothing.
5072TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5074
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005075 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005076 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5077 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005078 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005079
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005080 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005081 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5082 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005083 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005084
5085 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005086 mDispatcher->onWindowInfosChanged(
5087 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005088
5089 PointF pointInFirst = {300, 200};
5090 PointF pointInSecond = {300, 600};
5091
5092 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005093 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5094 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5095 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005096 // Only the first window should get the down event
5097 firstWindow->consumeMotionDown();
5098 secondWindow->assertNoEvents();
5099
5100 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005101 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5102 ADISPLAY_ID_DEFAULT,
5103 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005104 // The first window gets a move and the second a down
5105 firstWindow->consumeMotionMove();
5106 secondWindow->consumeMotionDown();
5107
5108 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005109 const bool transferred =
5110 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005111 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5112 ASSERT_FALSE(transferred);
5113 firstWindow->assertNoEvents();
5114 secondWindow->assertNoEvents();
5115
5116 // The rest of the dispatch should proceed as normal
5117 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005118 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5119 ADISPLAY_ID_DEFAULT,
5120 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005121 // The first window gets MOVE and the second gets pointer up
5122 firstWindow->consumeMotionMove();
5123 secondWindow->consumeMotionUp();
5124
5125 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005126 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5127 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005128 // The first window gets nothing and the second gets up
5129 firstWindow->consumeMotionUp();
5130 secondWindow->assertNoEvents();
5131}
5132
Arthur Hungabbb9d82021-09-01 14:52:30 +00005133// This case will create two windows and one mirrored window on the default display and mirror
5134// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5135// the windows info of second display before default display.
5136TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5138 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005139 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005140 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005141 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005142 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005143 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005144
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005145 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005146 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005147
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005148 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005149 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005150
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005151 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005152 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005153
5154 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005155 mDispatcher->onWindowInfosChanged(
5156 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5157 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5158 *secondWindowInPrimary->getInfo()},
5159 {},
5160 0,
5161 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005162
5163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005164 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005165 {50, 50}))
5166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5167
5168 // Window should receive motion event.
5169 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5170
5171 // Transfer touch focus
5172 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5173 secondWindowInPrimary->getToken()));
5174 // The first window gets cancel.
5175 firstWindowInPrimary->consumeMotionCancel();
5176 secondWindowInPrimary->consumeMotionDown();
5177
5178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005179 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005180 ADISPLAY_ID_DEFAULT, {150, 50}))
5181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5182 firstWindowInPrimary->assertNoEvents();
5183 secondWindowInPrimary->consumeMotionMove();
5184
5185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005186 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005187 {150, 50}))
5188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5189 firstWindowInPrimary->assertNoEvents();
5190 secondWindowInPrimary->consumeMotionUp();
5191}
5192
5193// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5194// 'transferTouch' api.
5195TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5197 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005198 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005199 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005200 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005201 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005202 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005203
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005204 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005205 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005206
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005207 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005208 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005209
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005210 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005211 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005212
5213 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005214 mDispatcher->onWindowInfosChanged(
5215 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5216 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5217 *secondWindowInPrimary->getInfo()},
5218 {},
5219 0,
5220 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005221
5222 // Touch on second display.
5223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005224 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5225 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005226 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5227
5228 // Window should receive motion event.
5229 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5230
5231 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005232 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005233
5234 // The first window gets cancel.
5235 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5236 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5237
5238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005239 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005240 SECOND_DISPLAY_ID, {150, 50}))
5241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5242 firstWindowInPrimary->assertNoEvents();
5243 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5244
5245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005246 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5248 firstWindowInPrimary->assertNoEvents();
5249 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5250}
5251
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005252TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005253 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005254 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5255 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005256
Vishnu Nair47074b82020-08-14 11:54:47 -07005257 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005259 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005260
5261 window->consumeFocusEvent(true);
5262
Prabir Pradhan678438e2023-04-13 19:32:51 +00005263 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005264
5265 // Window should receive key down event.
5266 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005267
5268 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005269 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005270 mFakePolicy->assertUserActivityPoked();
5271}
5272
5273TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5275 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5276 "Fake Window", ADISPLAY_ID_DEFAULT);
5277
5278 window->setDisableUserActivity(true);
5279 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005280 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005281 setFocusedWindow(window);
5282
5283 window->consumeFocusEvent(true);
5284
5285 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5286
5287 // Window should receive key down event.
5288 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5289
5290 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005291 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005292 mFakePolicy->assertUserActivityNotPoked();
5293}
5294
5295TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5296 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5297 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5298 "Fake Window", ADISPLAY_ID_DEFAULT);
5299
5300 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005301 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005302 setFocusedWindow(window);
5303
5304 window->consumeFocusEvent(true);
5305
5306 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5307 mDispatcher->waitForIdle();
5308
5309 // System key is not passed down
5310 window->assertNoEvents();
5311
5312 // Should have poked user activity
5313 mFakePolicy->assertUserActivityPoked();
5314}
5315
5316TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5318 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5319 "Fake Window", ADISPLAY_ID_DEFAULT);
5320
5321 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005322 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005323 setFocusedWindow(window);
5324
5325 window->consumeFocusEvent(true);
5326
5327 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5328 mDispatcher->waitForIdle();
5329
5330 // System key is not passed down
5331 window->assertNoEvents();
5332
5333 // Should have poked user activity
5334 mFakePolicy->assertUserActivityPoked();
5335}
5336
5337TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5339 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5340 "Fake Window", ADISPLAY_ID_DEFAULT);
5341
5342 window->setDisableUserActivity(true);
5343 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005344 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005345 setFocusedWindow(window);
5346
5347 window->consumeFocusEvent(true);
5348
5349 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5350 mDispatcher->waitForIdle();
5351
5352 // System key is not passed down
5353 window->assertNoEvents();
5354
5355 // Should have poked user activity
5356 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005357}
5358
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005359TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5361 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5362 "Fake Window", ADISPLAY_ID_DEFAULT);
5363
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005364 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005365
5366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005367 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005368 ADISPLAY_ID_DEFAULT, {100, 100}))
5369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5370
5371 window->consumeMotionEvent(
5372 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5373
5374 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005375 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005376 mFakePolicy->assertUserActivityPoked();
5377}
5378
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005379TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005381 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5382 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005383
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005384 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005385
Prabir Pradhan678438e2023-04-13 19:32:51 +00005386 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005387 mDispatcher->waitForIdle();
5388
5389 window->assertNoEvents();
5390}
5391
5392// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5393TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5396 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005398 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005399
5400 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005401 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005402 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005403 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5404 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005405
5406 // Window should receive only the motion event
5407 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5408 window->assertNoEvents(); // Key event or focus event will not be received
5409}
5410
arthurhungea3f4fc2020-12-21 23:18:53 +08005411TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5413
arthurhungea3f4fc2020-12-21 23:18:53 +08005414 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005415 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5416 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005417 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005418
arthurhungea3f4fc2020-12-21 23:18:53 +08005419 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005420 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5421 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005422 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005423
5424 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005425 mDispatcher->onWindowInfosChanged(
5426 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005427
5428 PointF pointInFirst = {300, 200};
5429 PointF pointInSecond = {300, 600};
5430
5431 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005432 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5433 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5434 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005435 // Only the first window should get the down event
5436 firstWindow->consumeMotionDown();
5437 secondWindow->assertNoEvents();
5438
5439 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005440 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5441 ADISPLAY_ID_DEFAULT,
5442 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005443 // The first window gets a move and the second a down
5444 firstWindow->consumeMotionMove();
5445 secondWindow->consumeMotionDown();
5446
5447 // Send pointer cancel to the second window
5448 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005449 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005450 {pointInFirst, pointInSecond});
5451 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005452 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005453 // The first window gets move and the second gets cancel.
5454 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5455 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5456
5457 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005458 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5459 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005460 // The first window gets up and the second gets nothing.
5461 firstWindow->consumeMotionUp();
5462 secondWindow->assertNoEvents();
5463}
5464
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005465TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5467
5468 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005469 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005470 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005471 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5472 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5473 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5474
Harry Cutts33476232023-01-30 19:57:29 +00005475 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005476 window->assertNoEvents();
5477 mDispatcher->waitForIdle();
5478}
5479
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005480using InputDispatcherMonitorTest = InputDispatcherTest;
5481
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005482/**
5483 * Two entities that receive touch: A window, and a global monitor.
5484 * The touch goes to the window, and then the window disappears.
5485 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5486 * for the monitor, as well.
5487 * 1. foregroundWindow
5488 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5489 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005490TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5492 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005493 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005494
Prabir Pradhanfb549072023-10-05 19:17:36 +00005495 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005496
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005497 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005499 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005500 {100, 200}))
5501 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5502
5503 // Both the foreground window and the global monitor should receive the touch down
5504 window->consumeMotionDown();
5505 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5506
5507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005508 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005509 ADISPLAY_ID_DEFAULT, {110, 200}))
5510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5511
5512 window->consumeMotionMove();
5513 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5514
5515 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005516 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005517 window->consumeMotionCancel();
5518 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5519
5520 // If more events come in, there will be no more foreground window to send them to. This will
5521 // cause a cancel for the monitor, as well.
5522 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005523 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005524 ADISPLAY_ID_DEFAULT, {120, 200}))
5525 << "Injection should fail because the window was removed";
5526 window->assertNoEvents();
5527 // Global monitor now gets the cancel
5528 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5529}
5530
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005531TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005533 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5534 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005535 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005536
Prabir Pradhanfb549072023-10-05 19:17:36 +00005537 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005538
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005540 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005541 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005542 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005543 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005544}
5545
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005546TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005547 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005548
Chris Yea209fde2020-07-22 13:54:51 -07005549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5551 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005552 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005553
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005555 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005557 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005558 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005559
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005560 // Pilfer pointers from the monitor.
5561 // This should not do anything and the window should continue to receive events.
5562 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005563
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005565 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005566 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005568
5569 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5570 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005571}
5572
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005573TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005575 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5576 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005577 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005578 window->setWindowOffset(20, 40);
5579 window->setWindowTransform(0, 1, -1, 0);
5580
Prabir Pradhanfb549072023-10-05 19:17:36 +00005581 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005582
5583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005584 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5586 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5587 MotionEvent* event = monitor.consumeMotion();
5588 // Even though window has transform, gesture monitor must not.
5589 ASSERT_EQ(ui::Transform(), event->getTransform());
5590}
5591
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005592TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005594 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005595
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005596 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005597 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005598 << "Injection should fail if there is a monitor, but no touchable window";
5599 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005600}
5601
chaviw81e2bb92019-12-18 15:03:51 -08005602TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005604 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5605 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005606
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005607 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005608
5609 NotifyMotionArgs motionArgs =
5610 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5611 ADISPLAY_ID_DEFAULT);
5612
Prabir Pradhan678438e2023-04-13 19:32:51 +00005613 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005614 // Window should receive motion down event.
5615 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5616
5617 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005618 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005619 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5620 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5621 motionArgs.pointerCoords[0].getX() - 10);
5622
Prabir Pradhan678438e2023-04-13 19:32:51 +00005623 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005624 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005625 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005626}
5627
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005628/**
5629 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5630 * the device default right away. In the test scenario, we check both the default value,
5631 * and the action of enabling / disabling.
5632 */
5633TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005635 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5636 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005637 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005638
5639 // Set focused application.
5640 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005641 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005642
5643 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005644 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005645 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005646 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005647
5648 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005649 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005650 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005651 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005652
5653 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005654 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005655 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005656 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005657 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005659 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005660 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005661
5662 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005663 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005664 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005665 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005666
5667 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005668 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005669 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005670 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005671 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005673 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005674 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005675
5676 window->assertNoEvents();
5677}
5678
Gang Wange9087892020-01-07 12:17:14 -05005679TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5682 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005683
5684 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005685 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005688 setFocusedWindow(window);
5689
Harry Cutts33476232023-01-30 19:57:29 +00005690 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005691
Prabir Pradhan678438e2023-04-13 19:32:51 +00005692 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5693 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005694
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005695 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005696 ASSERT_NE(event, nullptr);
5697
5698 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5699 ASSERT_NE(verified, nullptr);
5700 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5701
5702 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5703 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5704 ASSERT_EQ(keyArgs.source, verified->source);
5705 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5706
5707 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5708
5709 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005710 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005711 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005712 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5713 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5714 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5715 ASSERT_EQ(0, verifiedKey.repeatCount);
5716}
5717
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005718TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005720 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5721 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005722
5723 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5724
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005725 ui::Transform transform;
5726 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5727
5728 gui::DisplayInfo displayInfo;
5729 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5730 displayInfo.transform = transform;
5731
Patrick Williamsd828f302023-04-28 17:52:08 -05005732 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005733
Prabir Pradhan678438e2023-04-13 19:32:51 +00005734 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005735 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5736 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005737 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005738
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005739 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005740 ASSERT_NE(event, nullptr);
5741
5742 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5743 ASSERT_NE(verified, nullptr);
5744 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5745
5746 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5747 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5748 EXPECT_EQ(motionArgs.source, verified->source);
5749 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5750
5751 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5752
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005753 const vec2 rawXY =
5754 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5755 motionArgs.pointerCoords[0].getXYValue());
5756 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5757 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005758 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005759 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005760 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005761 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5762 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5763}
5764
chaviw09c8d2d2020-08-24 15:48:26 -07005765/**
5766 * Ensure that separate calls to sign the same data are generating the same key.
5767 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5768 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5769 * tests.
5770 */
5771TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5772 KeyEvent event = getTestKeyEvent();
5773 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5774
5775 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5776 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5777 ASSERT_EQ(hmac1, hmac2);
5778}
5779
5780/**
5781 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5782 */
5783TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5784 KeyEvent event = getTestKeyEvent();
5785 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5786 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5787
5788 verifiedEvent.deviceId += 1;
5789 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5790
5791 verifiedEvent.source += 1;
5792 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5793
5794 verifiedEvent.eventTimeNanos += 1;
5795 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5796
5797 verifiedEvent.displayId += 1;
5798 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5799
5800 verifiedEvent.action += 1;
5801 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5802
5803 verifiedEvent.downTimeNanos += 1;
5804 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5805
5806 verifiedEvent.flags += 1;
5807 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5808
5809 verifiedEvent.keyCode += 1;
5810 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5811
5812 verifiedEvent.scanCode += 1;
5813 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5814
5815 verifiedEvent.metaState += 1;
5816 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5817
5818 verifiedEvent.repeatCount += 1;
5819 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5820}
5821
Vishnu Nair958da932020-08-21 17:12:37 -07005822TEST_F(InputDispatcherTest, SetFocusedWindow) {
5823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5824 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005825 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005826 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005827 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005828 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5829
5830 // Top window is also focusable but is not granted focus.
5831 windowTop->setFocusable(true);
5832 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005833 mDispatcher->onWindowInfosChanged(
5834 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005835 setFocusedWindow(windowSecond);
5836
5837 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005839 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005840
5841 // Focused window should receive event.
5842 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5843 windowTop->assertNoEvents();
5844}
5845
5846TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5848 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005849 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005850 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5851
5852 window->setFocusable(true);
5853 // Release channel for window is no longer valid.
5854 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005856 setFocusedWindow(window);
5857
5858 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005859 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005860
5861 // window channel is invalid, so it should not receive any input event.
5862 window->assertNoEvents();
5863}
5864
5865TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5867 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005868 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005869 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005870 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5871
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005872 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005873 setFocusedWindow(window);
5874
5875 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005876 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005877
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005878 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005879 window->assertNoEvents();
5880}
5881
5882TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5884 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005885 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005886 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005887 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005888 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5889
5890 windowTop->setFocusable(true);
5891 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005892 mDispatcher->onWindowInfosChanged(
5893 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005894 setFocusedWindow(windowTop);
5895 windowTop->consumeFocusEvent(true);
5896
Chavi Weingarten847e8512023-03-29 00:26:09 +00005897 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005898 mDispatcher->onWindowInfosChanged(
5899 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005900 windowSecond->consumeFocusEvent(true);
5901 windowTop->consumeFocusEvent(false);
5902
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005904 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005905
5906 // Focused window should receive event.
5907 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5908}
5909
Chavi Weingarten847e8512023-03-29 00:26:09 +00005910TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005911 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5912 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005913 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005914 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005915 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005916 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5917
5918 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005919 windowSecond->setFocusable(false);
5920 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005921 mDispatcher->onWindowInfosChanged(
5922 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005923 setFocusedWindow(windowTop);
5924 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005925
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005927 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005928
5929 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005930 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005931 windowSecond->assertNoEvents();
5932}
5933
5934TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5936 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005937 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005938 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005939 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5940 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005941 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5942
5943 window->setFocusable(true);
5944 previousFocusedWindow->setFocusable(true);
5945 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005946 mDispatcher->onWindowInfosChanged(
5947 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005948 setFocusedWindow(previousFocusedWindow);
5949 previousFocusedWindow->consumeFocusEvent(true);
5950
5951 // Requesting focus on invisible window takes focus from currently focused window.
5952 setFocusedWindow(window);
5953 previousFocusedWindow->consumeFocusEvent(false);
5954
5955 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005957 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5958 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005959
5960 // Window does not get focus event or key down.
5961 window->assertNoEvents();
5962
5963 // Window becomes visible.
5964 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005965 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005966
5967 // Window receives focus event.
5968 window->consumeFocusEvent(true);
5969 // Focused window receives key down.
5970 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5971}
5972
Vishnu Nair599f1412021-06-21 10:39:58 -07005973TEST_F(InputDispatcherTest, DisplayRemoved) {
5974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5975 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005976 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005977 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5978
5979 // window is granted focus.
5980 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005981 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005982 setFocusedWindow(window);
5983 window->consumeFocusEvent(true);
5984
5985 // When a display is removed window loses focus.
5986 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5987 window->consumeFocusEvent(false);
5988}
5989
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005990/**
5991 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5992 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5993 * of the 'slipperyEnterWindow'.
5994 *
5995 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5996 * a way so that the touched location is no longer covered by the top window.
5997 *
5998 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5999 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6000 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6001 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6002 * with ACTION_DOWN).
6003 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6004 * window moved itself away from the touched location and had Flag::SLIPPERY.
6005 *
6006 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6007 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6008 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6009 *
6010 * In this test, we ensure that the event received by the bottom window has
6011 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6012 */
6013TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006014 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006015 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006016
6017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6018 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6019
6020 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006021 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006022 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006023 // Make sure this one overlaps the bottom window
6024 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6025 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6026 // one. Windows with the same owner are not considered to be occluding each other.
6027 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6028
6029 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006030 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006031 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6032
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006033 mDispatcher->onWindowInfosChanged(
6034 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006035
6036 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006037 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6038 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6039 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006040 slipperyExitWindow->consumeMotionDown();
6041 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006042 mDispatcher->onWindowInfosChanged(
6043 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006044
Prabir Pradhan678438e2023-04-13 19:32:51 +00006045 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6046 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6047 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006048
6049 slipperyExitWindow->consumeMotionCancel();
6050
6051 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6052 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6053}
6054
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006055/**
6056 * Two windows, one on the left and another on the right. The left window is slippery. The right
6057 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6058 * touch moves from the left window into the right window, the gesture should continue to go to the
6059 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6060 * reproduces a crash.
6061 */
6062TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6063 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6064
6065 sp<FakeWindowHandle> leftSlipperyWindow =
6066 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6067 leftSlipperyWindow->setSlippery(true);
6068 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6069
6070 sp<FakeWindowHandle> rightDropTouchesWindow =
6071 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6072 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6073 rightDropTouchesWindow->setDropInput(true);
6074
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006075 mDispatcher->onWindowInfosChanged(
6076 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006077
6078 // Start touch in the left window
6079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6080 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6081 .build());
6082 leftSlipperyWindow->consumeMotionDown();
6083
6084 // And move it into the right window
6085 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6086 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6087 .build());
6088
6089 // Since the right window isn't eligible to receive input, touch does not slip.
6090 // The left window continues to receive the gesture.
6091 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6092 rightDropTouchesWindow->assertNoEvents();
6093}
6094
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006095/**
6096 * A single window is on screen first. Touch is injected into that window. Next, a second window
6097 * appears. Since the first window is slippery, touch will move from the first window to the second.
6098 */
6099TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6101 sp<FakeWindowHandle> originalWindow =
6102 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6103 originalWindow->setFrame(Rect(0, 0, 200, 200));
6104 originalWindow->setSlippery(true);
6105
6106 sp<FakeWindowHandle> appearingWindow =
6107 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6108 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6109
6110 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6111
6112 // Touch down on the original window
6113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6114 injectMotionEvent(*mDispatcher,
6115 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6116 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6117 .build()));
6118 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6119
6120 // Now, a new window appears. This could be, for example, a notification shade that appears
6121 // after user starts to drag down on the launcher window.
6122 mDispatcher->onWindowInfosChanged(
6123 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6125 injectMotionEvent(*mDispatcher,
6126 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6127 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6128 .build()));
6129 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6130 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6132 injectMotionEvent(*mDispatcher,
6133 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6134 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6135 .build()));
6136 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6137
6138 originalWindow->assertNoEvents();
6139 appearingWindow->assertNoEvents();
6140}
6141
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006142TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006143 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6145
6146 sp<FakeWindowHandle> leftWindow =
6147 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6148 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006149 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006150
6151 sp<FakeWindowHandle> rightSpy =
6152 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6153 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006154 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006155 rightSpy->setSpy(true);
6156 rightSpy->setTrustedOverlay(true);
6157
6158 sp<FakeWindowHandle> rightWindow =
6159 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6160 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006161 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006162
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006163 mDispatcher->onWindowInfosChanged(
6164 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006165
6166 // Touch in the left window
6167 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6168 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6169 .build());
6170 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6171 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006172 ASSERT_NO_FATAL_FAILURE(
6173 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006174
6175 // Touch another finger over the right windows
6176 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6177 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6178 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6179 .build());
6180 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6181 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6182 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6183 mDispatcher->waitForIdle();
6184 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006185 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6186 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006187
6188 // Release finger over left window. The UP actions are not treated as device interaction.
6189 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6190 // is part of the UP action, we do not treat this as device interaction.
6191 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6192 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6193 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6194 .build());
6195 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6196 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6197 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6198 mDispatcher->waitForIdle();
6199 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6200
6201 // Move remaining finger
6202 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6203 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6204 .build());
6205 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6206 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6207 mDispatcher->waitForIdle();
6208 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006209 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006210
6211 // Release all fingers
6212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6213 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6214 .build());
6215 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6216 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6217 mDispatcher->waitForIdle();
6218 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6219}
6220
6221TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6223
6224 sp<FakeWindowHandle> window =
6225 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6226 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006227 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006228
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006229 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006230 setFocusedWindow(window);
6231 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6232
6233 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6234 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6235 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006236 ASSERT_NO_FATAL_FAILURE(
6237 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006238
6239 // The UP actions are not treated as device interaction.
6240 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6241 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6242 mDispatcher->waitForIdle();
6243 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6244}
6245
Garfield Tan1c7bc862020-01-28 13:24:04 -08006246class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6247protected:
6248 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6249 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6250
Chris Yea209fde2020-07-22 13:54:51 -07006251 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006252 sp<FakeWindowHandle> mWindow;
6253
6254 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006255 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006256 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006257 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006258 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006259 ASSERT_EQ(OK, mDispatcher->start());
6260
6261 setUpWindow();
6262 }
6263
6264 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006265 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006266 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006267
Vishnu Nair47074b82020-08-14 11:54:47 -07006268 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006269 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006270 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006271 mWindow->consumeFocusEvent(true);
6272 }
6273
Chris Ye2ad95392020-09-01 13:44:44 -07006274 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006275 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006276 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006277 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006278 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006279
6280 // Window should receive key down event.
6281 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6282 }
6283
6284 void expectKeyRepeatOnce(int32_t repeatCount) {
6285 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006286 mWindow->consumeKeyEvent(
6287 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006288 }
6289
Chris Ye2ad95392020-09-01 13:44:44 -07006290 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006291 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006292 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006293 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006294 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006295
6296 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006297 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006298 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006299 }
6300};
6301
6302TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006303 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006304 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6305 expectKeyRepeatOnce(repeatCount);
6306 }
6307}
6308
6309TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006310 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006311 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6312 expectKeyRepeatOnce(repeatCount);
6313 }
Harry Cutts33476232023-01-30 19:57:29 +00006314 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006315 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006316 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6317 expectKeyRepeatOnce(repeatCount);
6318 }
6319}
6320
6321TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006322 sendAndConsumeKeyDown(/*deviceId=*/1);
6323 expectKeyRepeatOnce(/*repeatCount=*/1);
6324 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006325 mWindow->assertNoEvents();
6326}
6327
6328TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006329 sendAndConsumeKeyDown(/*deviceId=*/1);
6330 expectKeyRepeatOnce(/*repeatCount=*/1);
6331 sendAndConsumeKeyDown(/*deviceId=*/2);
6332 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006333 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006334 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006335 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006336 expectKeyRepeatOnce(/*repeatCount=*/2);
6337 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006338 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006339 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006340 mWindow->assertNoEvents();
6341}
6342
6343TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006344 sendAndConsumeKeyDown(/*deviceId=*/1);
6345 expectKeyRepeatOnce(/*repeatCount=*/1);
6346 sendAndConsumeKeyDown(/*deviceId=*/2);
6347 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006348 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006349 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006350 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006351 mWindow->assertNoEvents();
6352}
6353
liushenxiang42232912021-05-21 20:24:09 +08006354TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6355 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006356 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006357 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006358 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6359 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6360 mWindow->assertNoEvents();
6361}
6362
Garfield Tan1c7bc862020-01-28 13:24:04 -08006363TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006364 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006365 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006366 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006367 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006368 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6369 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6370 IdGenerator::getSource(repeatEvent->getId()));
6371 }
6372}
6373
6374TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006375 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006376 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006377
6378 std::unordered_set<int32_t> idSet;
6379 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006380 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006381 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6382 int32_t id = repeatEvent->getId();
6383 EXPECT_EQ(idSet.end(), idSet.find(id));
6384 idSet.insert(id);
6385 }
6386}
6387
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006388/* Test InputDispatcher for MultiDisplay */
6389class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6390public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006391 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006392 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006393
Chris Yea209fde2020-07-22 13:54:51 -07006394 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006395 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006396 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006397
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006398 // Set focus window for primary display, but focused display would be second one.
6399 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006400 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006401 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6402
Vishnu Nair958da932020-08-21 17:12:37 -07006403 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006404 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006405
Chris Yea209fde2020-07-22 13:54:51 -07006406 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006407 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006408 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006409 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006410 // Set focus display to second one.
6411 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6412 // Set focus window for second display.
6413 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006414 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006415 mDispatcher->onWindowInfosChanged(
6416 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006417 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006418 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006419 }
6420
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006421 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006422 InputDispatcherTest::TearDown();
6423
Chris Yea209fde2020-07-22 13:54:51 -07006424 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006425 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006426 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006427 windowInSecondary.clear();
6428 }
6429
6430protected:
Chris Yea209fde2020-07-22 13:54:51 -07006431 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006432 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006433 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006434 sp<FakeWindowHandle> windowInSecondary;
6435};
6436
6437TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6438 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006440 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006442 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006443 windowInSecondary->assertNoEvents();
6444
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006445 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006447 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006448 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006449 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006450 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006451}
6452
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006453TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006454 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006456 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006457 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006458 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006459 windowInSecondary->assertNoEvents();
6460
6461 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006462 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006463 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006464 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006465 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006466
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006467 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006468 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006469
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006470 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006471 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006472 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006473
6474 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006475 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006476 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006477 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006478 windowInSecondary->assertNoEvents();
6479}
6480
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006481// Test per-display input monitors for motion event.
6482TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006483 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006484 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006485 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006486 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006487
6488 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006490 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006492 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006493 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006494 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006495 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006496
6497 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006499 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006500 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006501 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006502 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006503 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006504 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006505
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006506 // Lift up the touch from the second display
6507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006508 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006509 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6510 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6511 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6512
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006513 // Test inject a non-pointer motion event.
6514 // If specific a display, it will dispatch to the focused window of particular display,
6515 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006517 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006518 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006519 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006520 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006521 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006522 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006523}
6524
6525// Test per-display input monitors for key event.
6526TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006527 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006528 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006529 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006530 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006531 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006532
6533 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006535 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006536 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006537 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006538 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006539 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006540}
6541
Vishnu Nair958da932020-08-21 17:12:37 -07006542TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6543 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006544 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006545 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006546 mDispatcher->onWindowInfosChanged(
6547 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6548 *windowInSecondary->getInfo()},
6549 {},
6550 0,
6551 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006552 setFocusedWindow(secondWindowInPrimary);
6553 windowInPrimary->consumeFocusEvent(false);
6554 secondWindowInPrimary->consumeFocusEvent(true);
6555
6556 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6558 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006559 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006560 windowInPrimary->assertNoEvents();
6561 windowInSecondary->assertNoEvents();
6562 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6563}
6564
Arthur Hungdfd528e2021-12-08 13:23:04 +00006565TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6566 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006567 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006568 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006569 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006570
6571 // Test touch down on primary display.
6572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006573 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006574 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6575 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6576 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6577
6578 // Test touch down on second display.
6579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006580 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006581 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6582 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6583 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6584
6585 // Trigger cancel touch.
6586 mDispatcher->cancelCurrentTouch();
6587 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6588 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6589 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6590 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6591
6592 // Test inject a move motion event, no window/monitor should receive the event.
6593 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006594 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006595 ADISPLAY_ID_DEFAULT, {110, 200}))
6596 << "Inject motion event should return InputEventInjectionResult::FAILED";
6597 windowInPrimary->assertNoEvents();
6598 monitorInPrimary.assertNoEvents();
6599
6600 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006601 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006602 SECOND_DISPLAY_ID, {110, 200}))
6603 << "Inject motion event should return InputEventInjectionResult::FAILED";
6604 windowInSecondary->assertNoEvents();
6605 monitorInSecondary.assertNoEvents();
6606}
6607
Jackal Guof9696682018-10-05 12:23:23 +08006608class InputFilterTest : public InputDispatcherTest {
6609protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006610 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6611 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006612 NotifyMotionArgs motionArgs;
6613
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006614 motionArgs =
6615 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006616 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006617 motionArgs =
6618 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006619 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006620 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006621 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006622 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006623 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006624 } else {
6625 mFakePolicy->assertFilterInputEventWasNotCalled();
6626 }
6627 }
6628
6629 void testNotifyKey(bool expectToBeFiltered) {
6630 NotifyKeyArgs keyArgs;
6631
6632 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006633 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006634 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006635 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006636 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006637
6638 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006639 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006640 } else {
6641 mFakePolicy->assertFilterInputEventWasNotCalled();
6642 }
6643 }
6644};
6645
6646// Test InputFilter for MotionEvent
6647TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6648 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006649 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6650 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006651
6652 // Enable InputFilter
6653 mDispatcher->setInputFilterEnabled(true);
6654 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006655 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6656 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006657
6658 // Disable InputFilter
6659 mDispatcher->setInputFilterEnabled(false);
6660 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006661 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6662 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006663}
6664
6665// Test InputFilter for KeyEvent
6666TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6667 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006668 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006669
6670 // Enable InputFilter
6671 mDispatcher->setInputFilterEnabled(true);
6672 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006673 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006674
6675 // Disable InputFilter
6676 mDispatcher->setInputFilterEnabled(false);
6677 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006678 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006679}
6680
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006681// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6682// logical display coordinate space.
6683TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6684 ui::Transform firstDisplayTransform;
6685 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6686 ui::Transform secondDisplayTransform;
6687 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6688
6689 std::vector<gui::DisplayInfo> displayInfos(2);
6690 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6691 displayInfos[0].transform = firstDisplayTransform;
6692 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6693 displayInfos[1].transform = secondDisplayTransform;
6694
Patrick Williamsd828f302023-04-28 17:52:08 -05006695 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006696
6697 // Enable InputFilter
6698 mDispatcher->setInputFilterEnabled(true);
6699
6700 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006701 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6702 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006703}
6704
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006705class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6706protected:
6707 virtual void SetUp() override {
6708 InputDispatcherTest::SetUp();
6709
6710 /**
6711 * We don't need to enable input filter to test the injected event policy, but we enabled it
6712 * here to make the tests more realistic, since this policy only matters when inputfilter is
6713 * on.
6714 */
6715 mDispatcher->setInputFilterEnabled(true);
6716
6717 std::shared_ptr<InputApplicationHandle> application =
6718 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006719 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6720 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006721
6722 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6723 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006724 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006725 setFocusedWindow(mWindow);
6726 mWindow->consumeFocusEvent(true);
6727 }
6728
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006729 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6730 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006731 KeyEvent event;
6732
6733 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6734 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6735 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006736 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006737 const int32_t additionalPolicyFlags =
6738 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006740 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006741 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006742 policyFlags | additionalPolicyFlags));
6743
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006744 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006745 }
6746
6747 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6748 int32_t flags) {
6749 MotionEvent event;
6750 PointerProperties pointerProperties[1];
6751 PointerCoords pointerCoords[1];
6752 pointerProperties[0].clear();
6753 pointerProperties[0].id = 0;
6754 pointerCoords[0].clear();
6755 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6756 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6757
6758 ui::Transform identityTransform;
6759 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6760 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6761 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6762 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6763 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006764 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006765 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006766 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006767
6768 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006770 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006771 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006772 policyFlags | additionalPolicyFlags));
6773
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006774 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006775 }
6776
6777private:
6778 sp<FakeWindowHandle> mWindow;
6779};
6780
6781TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006782 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6783 // filter. Without it, the event will no different from a regularly injected event, and the
6784 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006785 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6786 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006787}
6788
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006789TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006790 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006791 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006792 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6793}
6794
6795TEST_F(InputFilterInjectionPolicyTest,
6796 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6797 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006798 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006799 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006800}
6801
6802TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006803 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6804 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006805}
6806
chaviwfd6d3512019-03-25 13:23:49 -07006807class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006808 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006809 InputDispatcherTest::SetUp();
6810
Chris Yea209fde2020-07-22 13:54:51 -07006811 std::shared_ptr<FakeApplicationHandle> application =
6812 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006813 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006814 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006815 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006816
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006817 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006818 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006819 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006820
6821 // Set focused application.
6822 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006823 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006824
6825 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006826 mDispatcher->onWindowInfosChanged(
6827 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006828 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006829 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006830 }
6831
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006832 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006833 InputDispatcherTest::TearDown();
6834
6835 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006836 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006837 }
6838
6839protected:
6840 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006841 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006842 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006843};
6844
6845// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6846// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6847// the onPointerDownOutsideFocus callback.
6848TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006850 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006851 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006853 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006854
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006855 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006856 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6857}
6858
6859// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6860// DOWN on the window that doesn't have focus. Ensure no window received the
6861// onPointerDownOutsideFocus callback.
6862TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006864 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6865 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006867 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006868
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006869 ASSERT_TRUE(mDispatcher->waitForIdle());
6870 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006871}
6872
6873// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6874// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6875TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006877 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006878 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006879 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006880
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006881 ASSERT_TRUE(mDispatcher->waitForIdle());
6882 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006883}
6884
6885// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6886// DOWN on the window that already has focus. Ensure no window received the
6887// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006888TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006890 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006891 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006893 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006894
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006895 ASSERT_TRUE(mDispatcher->waitForIdle());
6896 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006897}
6898
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006899// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6900// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6901TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6902 const MotionEvent event =
6903 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6904 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006905 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006906 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6907 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006909 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6910 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6911
6912 ASSERT_TRUE(mDispatcher->waitForIdle());
6913 mFakePolicy->assertOnPointerDownWasNotCalled();
6914 // Ensure that the unfocused window did not receive any FOCUS events.
6915 mUnfocusedWindow->assertNoEvents();
6916}
6917
chaviwaf87b3e2019-10-01 16:59:28 -07006918// These tests ensures we can send touch events to a single client when there are multiple input
6919// windows that point to the same client token.
6920class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6921 virtual void SetUp() override {
6922 InputDispatcherTest::SetUp();
6923
Chris Yea209fde2020-07-22 13:54:51 -07006924 std::shared_ptr<FakeApplicationHandle> application =
6925 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006926 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6927 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006928 mWindow1->setFrame(Rect(0, 0, 100, 100));
6929
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006930 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6931 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006932 mWindow2->setFrame(Rect(100, 100, 200, 200));
6933
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006934 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006935 }
6936
6937protected:
6938 sp<FakeWindowHandle> mWindow1;
6939 sp<FakeWindowHandle> mWindow2;
6940
6941 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006942 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006943 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6944 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006945 }
6946
6947 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6948 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006949 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006950 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006951
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006952 ASSERT_NE(nullptr, motionEvent)
6953 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006954
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006955 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006956 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006957
6958 for (size_t i = 0; i < points.size(); i++) {
6959 float expectedX = points[i].x;
6960 float expectedY = points[i].y;
6961
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006962 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006963 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006964 << ", got " << motionEvent->getX(i);
6965 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006966 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006967 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006968 }
6969 }
chaviw9eaa22c2020-07-01 16:21:27 -07006970
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006971 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006972 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006973 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6974 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006975
6976 // Always consume from window1 since it's the window that has the InputReceiver
6977 consumeMotionEvent(mWindow1, action, expectedPoints);
6978 }
chaviwaf87b3e2019-10-01 16:59:28 -07006979};
6980
6981TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6982 // Touch Window 1
6983 PointF touchedPoint = {10, 10};
6984 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006985 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006986
6987 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006988 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006989
6990 // Touch Window 2
6991 touchedPoint = {150, 150};
6992 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006993 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006994}
6995
chaviw9eaa22c2020-07-01 16:21:27 -07006996TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6997 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006998 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006999 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007000
7001 // Touch Window 1
7002 PointF touchedPoint = {10, 10};
7003 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007004 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007005 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007006 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007007
7008 // Touch Window 2
7009 touchedPoint = {150, 150};
7010 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007011 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7012 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007013
chaviw9eaa22c2020-07-01 16:21:27 -07007014 // Update the transform so rotation is set
7015 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007016 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007017 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7018 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007019}
7020
chaviw9eaa22c2020-07-01 16:21:27 -07007021TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007022 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007023 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007024
7025 // Touch Window 1
7026 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7027 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007028 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007029
7030 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007031 touchedPoints.push_back(PointF{150, 150});
7032 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007033 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007034
chaviw9eaa22c2020-07-01 16:21:27 -07007035 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007036 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007037 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007038
chaviw9eaa22c2020-07-01 16:21:27 -07007039 // Update the transform so rotation is set for Window 2
7040 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007041 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007042 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007043 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007044}
7045
chaviw9eaa22c2020-07-01 16:21:27 -07007046TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007047 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007048 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007049
7050 // Touch Window 1
7051 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7052 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007053 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007054
7055 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007056 touchedPoints.push_back(PointF{150, 150});
7057 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007058
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007059 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007060
7061 // Move both windows
7062 touchedPoints = {{20, 20}, {175, 175}};
7063 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7064 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7065
chaviw9eaa22c2020-07-01 16:21:27 -07007066 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007067
chaviw9eaa22c2020-07-01 16:21:27 -07007068 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007069 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007070 expectedPoints.pop_back();
7071
7072 // Touch Window 2
7073 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007074 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007075 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007076 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007077
7078 // Move both windows
7079 touchedPoints = {{20, 20}, {175, 175}};
7080 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7081 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7082
7083 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007084}
7085
7086TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7087 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007088 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007089
7090 // Touch Window 1
7091 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7092 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007093 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007094
7095 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007096 touchedPoints.push_back(PointF{150, 150});
7097 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007098
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007099 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007100
7101 // Move both windows
7102 touchedPoints = {{20, 20}, {175, 175}};
7103 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7104 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7105
chaviw9eaa22c2020-07-01 16:21:27 -07007106 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007107}
7108
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007109/**
7110 * When one of the windows is slippery, the touch should not slip into the other window with the
7111 * same input channel.
7112 */
7113TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7114 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007115 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007116
7117 // Touch down in window 1
7118 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7119 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7120 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7121
7122 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7123 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7124 // getting generated.
7125 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7126 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7127
7128 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7129}
7130
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007131/**
7132 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7133 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7134 * that the pointer is hovering over may have a different transform.
7135 */
7136TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007137 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007138
7139 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007140 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7141 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7142 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007143 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7144 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007145 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7147 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7148 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007149 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7150 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7151 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7152}
7153
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007154class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7155 virtual void SetUp() override {
7156 InputDispatcherTest::SetUp();
7157
Chris Yea209fde2020-07-22 13:54:51 -07007158 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007159 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007160 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7161 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007162 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007163 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007164 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007165
7166 // Set focused application.
7167 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7168
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007169 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007170 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007171 mWindow->consumeFocusEvent(true);
7172 }
7173
7174 virtual void TearDown() override {
7175 InputDispatcherTest::TearDown();
7176 mWindow.clear();
7177 }
7178
7179protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007180 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007181 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007182 sp<FakeWindowHandle> mWindow;
7183 static constexpr PointF WINDOW_LOCATION = {20, 20};
7184
7185 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007187 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007188 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007190 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007191 WINDOW_LOCATION));
7192 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007193
7194 sp<FakeWindowHandle> addSpyWindow() {
7195 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007196 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007197 spy->setTrustedOverlay(true);
7198 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007199 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007200 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007201 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007202 return spy;
7203 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007204};
7205
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007206// Send a tap and respond, which should not cause an ANR.
7207TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7208 tapOnWindow();
7209 mWindow->consumeMotionDown();
7210 mWindow->consumeMotionUp();
7211 ASSERT_TRUE(mDispatcher->waitForIdle());
7212 mFakePolicy->assertNotifyAnrWasNotCalled();
7213}
7214
7215// Send a regular key and respond, which should not cause an ANR.
7216TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007218 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7219 ASSERT_TRUE(mDispatcher->waitForIdle());
7220 mFakePolicy->assertNotifyAnrWasNotCalled();
7221}
7222
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007223TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7224 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007225 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007226 mWindow->consumeFocusEvent(false);
7227
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007228 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007229 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7230 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007231 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007233 // Key will not go to window because we have no focused window.
7234 // The 'no focused window' ANR timer should start instead.
7235
7236 // Now, the focused application goes away.
7237 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7238 // The key should get dropped and there should be no ANR.
7239
7240 ASSERT_TRUE(mDispatcher->waitForIdle());
7241 mFakePolicy->assertNotifyAnrWasNotCalled();
7242}
7243
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007244// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007245// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7246// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007247TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007249 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007250 WINDOW_LOCATION));
7251
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007252 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7253 ASSERT_TRUE(sequenceNum);
7254 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007255 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007256
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007257 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007258 mWindow->consumeMotionEvent(
7259 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007260 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007261 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007262}
7263
7264// Send a key to the app and have the app not respond right away.
7265TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7266 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007268 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7269 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007270 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007271 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007272 ASSERT_TRUE(mDispatcher->waitForIdle());
7273}
7274
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007275// We have a focused application, but no focused window
7276TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007277 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007278 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279 mWindow->consumeFocusEvent(false);
7280
7281 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007283 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007284 WINDOW_LOCATION));
7285 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7286 mDispatcher->waitForIdle();
7287 mFakePolicy->assertNotifyAnrWasNotCalled();
7288
7289 // Once a focused event arrives, we get an ANR for this application
7290 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7291 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007292 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007293 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007294 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007295 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007296 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007297 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007298 ASSERT_TRUE(mDispatcher->waitForIdle());
7299}
7300
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007301/**
7302 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7303 * there will not be an ANR.
7304 */
7305TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7306 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007307 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007308 mWindow->consumeFocusEvent(false);
7309
7310 KeyEvent event;
7311 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7312 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7313
7314 // Define a valid key down event that is stale (too old).
7315 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007316 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007317 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007318
7319 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7320
7321 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007322 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007323 InputEventInjectionSync::WAIT_FOR_RESULT,
7324 INJECT_EVENT_TIMEOUT, policyFlags);
7325 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7326 << "Injection should fail because the event is stale";
7327
7328 ASSERT_TRUE(mDispatcher->waitForIdle());
7329 mFakePolicy->assertNotifyAnrWasNotCalled();
7330 mWindow->assertNoEvents();
7331}
7332
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007333// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007334// Make sure that we don't notify policy twice about the same ANR.
7335TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007336 const std::chrono::duration appTimeout = 400ms;
7337 mApplication->setDispatchingTimeout(appTimeout);
7338 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7339
Vishnu Nair47074b82020-08-14 11:54:47 -07007340 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007341 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007342 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007343
7344 // Once a focused event arrives, we get an ANR for this application
7345 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7346 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007347 const std::chrono::duration eventInjectionTimeout = 100ms;
7348 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007349 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007350 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007351 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7352 /*allowKeyRepeat=*/false);
7353 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7354 << "result=" << ftl::enum_string(result);
7355 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7356 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7357 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7358 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007359
Vishnu Naire4df8752022-09-08 09:17:55 -07007360 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007361 // ANR should not be raised again. It is up to policy to do that if it desires.
7362 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007363
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007364 // If we now get a focused window, the ANR should stop, but the policy handles that via
7365 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007366 ASSERT_TRUE(mDispatcher->waitForIdle());
7367}
7368
7369// We have a focused application, but no focused window
7370TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007371 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007372 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007373 mWindow->consumeFocusEvent(false);
7374
7375 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007376 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377
Vishnu Naire4df8752022-09-08 09:17:55 -07007378 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7379 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007380
7381 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007382 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007383 ASSERT_TRUE(mDispatcher->waitForIdle());
7384 mWindow->assertNoEvents();
7385}
7386
7387/**
7388 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7389 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7390 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7391 * the ANR mechanism should still work.
7392 *
7393 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7394 * DOWN event, while not responding on the second one.
7395 */
7396TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7397 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007398 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007399 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7400 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7401 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007402 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007403
7404 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007405 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007406 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7407 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7408 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007409 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007410
7411 // We have now sent down and up. Let's consume first event and then ANR on the second.
7412 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7413 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007414 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007415}
7416
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007417// A spy window can receive an ANR
7418TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7419 sp<FakeWindowHandle> spy = addSpyWindow();
7420
7421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007422 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007423 WINDOW_LOCATION));
7424 mWindow->consumeMotionDown();
7425
7426 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7427 ASSERT_TRUE(sequenceNum);
7428 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007429 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007430
7431 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007432 spy->consumeMotionEvent(
7433 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007434 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007435 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007436}
7437
7438// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007439// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007440TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7441 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007442
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007444 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007445 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007447
7448 // Stuck on the ACTION_UP
7449 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007450 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007451
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007452 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007453 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007454 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7455 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007456
7457 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7458 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007459 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007460 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007461 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007462}
7463
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007464// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007465// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007466TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7467 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007468
7469 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007470 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7471 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007472
7473 mWindow->consumeMotionDown();
7474 // Stuck on the ACTION_UP
7475 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007476 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007477
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007478 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007479 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007480 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7481 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007482
7483 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7484 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007485 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007486 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007487 spy->assertNoEvents();
7488}
7489
7490TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007491 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007492
Prabir Pradhanfb549072023-10-05 19:17:36 +00007493 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007494
7495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007496 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007497 WINDOW_LOCATION));
7498
7499 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7500 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7501 ASSERT_TRUE(consumeSeq);
7502
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007503 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7504 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007505
7506 monitor.finishEvent(*consumeSeq);
7507 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7508
7509 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007510 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007511}
7512
7513// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7514// process events, you don't get an anr. When the window later becomes unresponsive again, you
7515// get an ANR again.
7516// 1. tap -> block on ACTION_UP -> receive ANR
7517// 2. consume all pending events (= queue becomes healthy again)
7518// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7519TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7520 tapOnWindow();
7521
7522 mWindow->consumeMotionDown();
7523 // Block on ACTION_UP
7524 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007525 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007526 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7527 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007528 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007529 mWindow->assertNoEvents();
7530
7531 tapOnWindow();
7532 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007533 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007534 mWindow->consumeMotionUp();
7535
7536 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007537 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007538 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007539 mWindow->assertNoEvents();
7540}
7541
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007542// If a connection remains unresponsive for a while, make sure policy is only notified once about
7543// it.
7544TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007546 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007547 WINDOW_LOCATION));
7548
7549 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007550 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007551 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007552 // 'notifyConnectionUnresponsive' should only be called once per connection
7553 mFakePolicy->assertNotifyAnrWasNotCalled();
7554 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007555 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007556 mWindow->consumeMotionEvent(
7557 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007558 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007559 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007560 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007561 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007562}
7563
7564/**
7565 * 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 -07007566 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007567 *
7568 * Warning!!!
7569 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7570 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007571 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007572 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7573 *
7574 * If that value changes, this test should also change.
7575 */
7576TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7577 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007578 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007579
7580 tapOnWindow();
7581 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7582 ASSERT_TRUE(downSequenceNum);
7583 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7584 ASSERT_TRUE(upSequenceNum);
7585 // Don't finish the events yet, and send a key
7586 // Injection will "succeed" because we will eventually give up and send the key to the focused
7587 // window even if motions are still being processed. But because the injection timeout is short,
7588 // we will receive INJECTION_TIMED_OUT as the result.
7589
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007590 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007591 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7592 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007593 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007594 // Key will not be sent to the window, yet, because the window is still processing events
7595 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007596 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7597 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7598 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7599 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007600
7601 std::this_thread::sleep_for(500ms);
7602 // if we wait long enough though, dispatcher will give up, and still send the key
7603 // to the focused window, even though we have not yet finished the motion event
7604 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7605 mWindow->finishEvent(*downSequenceNum);
7606 mWindow->finishEvent(*upSequenceNum);
7607}
7608
7609/**
7610 * If a window is processing a motion event, and then a key event comes in, the key event should
7611 * not go to the focused window until the motion is processed.
7612 * If then a new motion comes in, then the pending key event should be going to the currently
7613 * focused window right away.
7614 */
7615TEST_F(InputDispatcherSingleWindowAnr,
7616 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7617 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007618 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007619
7620 tapOnWindow();
7621 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7622 ASSERT_TRUE(downSequenceNum);
7623 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7624 ASSERT_TRUE(upSequenceNum);
7625 // Don't finish the events yet, and send a key
7626 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007628 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7629 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007630 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007631 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7632 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7633 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7634 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007635
7636 // Now tap down again. It should cause the pending key to go to the focused window right away.
7637 tapOnWindow();
7638 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7639 // the other events yet. We can finish events in any order.
7640 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7641 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7642 mWindow->consumeMotionDown();
7643 mWindow->consumeMotionUp();
7644 mWindow->assertNoEvents();
7645}
7646
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007647/**
7648 * Send an event to the app and have the app not respond right away.
7649 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7650 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7651 * At some point, the window becomes responsive again.
7652 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7653 */
7654TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7655 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7656 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7657 .build());
7658
7659 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7660 ASSERT_TRUE(sequenceNum);
7661 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7662 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7663
7664 mWindow->finishEvent(*sequenceNum);
7665 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7666 ASSERT_TRUE(mDispatcher->waitForIdle());
7667 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7668
7669 // Now that the window is responsive, let's continue the gesture.
7670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7671 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7672 .build());
7673
7674 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7675 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7676 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7677 .build());
7678
7679 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7680 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7681 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7682 .build());
7683 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7684 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7685 .build());
7686 // We already canceled this pointer, so the window shouldn't get any new events.
7687 mWindow->assertNoEvents();
7688
7689 // Start another one.
7690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7691 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7692 .build());
7693 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7694}
7695
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007696class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7697 virtual void SetUp() override {
7698 InputDispatcherTest::SetUp();
7699
Chris Yea209fde2020-07-22 13:54:51 -07007700 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007701 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007702 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7703 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007704 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007705 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007706 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007707
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007708 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7709 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007710 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007711 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007712
7713 // Set focused application.
7714 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007715 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007716
7717 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007718 mDispatcher->onWindowInfosChanged(
7719 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007720 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007721 mFocusedWindow->consumeFocusEvent(true);
7722 }
7723
7724 virtual void TearDown() override {
7725 InputDispatcherTest::TearDown();
7726
7727 mUnfocusedWindow.clear();
7728 mFocusedWindow.clear();
7729 }
7730
7731protected:
Chris Yea209fde2020-07-22 13:54:51 -07007732 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007733 sp<FakeWindowHandle> mUnfocusedWindow;
7734 sp<FakeWindowHandle> mFocusedWindow;
7735 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7736 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7737 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7738
7739 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7740
7741 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7742
7743private:
7744 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007747 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007749 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007750 location));
7751 }
7752};
7753
7754// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7755// should be ANR'd first.
7756TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007759 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007761 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007762 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007763 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007764 // We consumed all events, so no ANR
7765 ASSERT_TRUE(mDispatcher->waitForIdle());
7766 mFakePolicy->assertNotifyAnrWasNotCalled();
7767
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007769 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007770 FOCUSED_WINDOW_LOCATION));
7771 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7772 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007773
7774 const std::chrono::duration timeout =
7775 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007776 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007777 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7778 // sequence to make it consistent
7779 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007780 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007781 mFocusedWindow->consumeMotionDown();
7782 // This cancel is generated because the connection was unresponsive
7783 mFocusedWindow->consumeMotionCancel();
7784 mFocusedWindow->assertNoEvents();
7785 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007786 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007787 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7788 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007789 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007790}
7791
7792// If we have 2 windows with identical timeouts that are both unresponsive,
7793// it doesn't matter which order they should have ANR.
7794// But we should receive ANR for both.
7795TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7796 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007797 mUnfocusedWindow->setDispatchingTimeout(
7798 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007799 mDispatcher->onWindowInfosChanged(
7800 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007801
7802 tapOnFocusedWindow();
7803 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007804 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007805 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7806 mFocusedWindow->getDispatchingTimeout(
7807 DISPATCHING_TIMEOUT)),
7808 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7809
7810 ASSERT_THAT(anrConnectionTokens,
7811 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7812 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007813
7814 ASSERT_TRUE(mDispatcher->waitForIdle());
7815 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007816
7817 mFocusedWindow->consumeMotionDown();
7818 mFocusedWindow->consumeMotionUp();
7819 mUnfocusedWindow->consumeMotionOutside();
7820
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007821 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7822 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007823
7824 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007825 ASSERT_THAT(responsiveTokens,
7826 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7827 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007828 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007829}
7830
7831// If a window is already not responding, the second tap on the same window should be ignored.
7832// We should also log an error to account for the dropped event (not tested here).
7833// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7834TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7835 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007836 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007837 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007838 // Receive the events, but don't respond
7839 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7840 ASSERT_TRUE(downEventSequenceNum);
7841 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7842 ASSERT_TRUE(upEventSequenceNum);
7843 const std::chrono::duration timeout =
7844 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007845 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007846
7847 // Tap once again
7848 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007849 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007850 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007851 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007852 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007853 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007854 FOCUSED_WINDOW_LOCATION));
7855 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7856 // valid touch target
7857 mUnfocusedWindow->assertNoEvents();
7858
7859 // Consume the first tap
7860 mFocusedWindow->finishEvent(*downEventSequenceNum);
7861 mFocusedWindow->finishEvent(*upEventSequenceNum);
7862 ASSERT_TRUE(mDispatcher->waitForIdle());
7863 // The second tap did not go to the focused window
7864 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007865 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007866 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7867 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007868 mFakePolicy->assertNotifyAnrWasNotCalled();
7869}
7870
7871// If you tap outside of all windows, there will not be ANR
7872TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007873 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007874 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007875 LOCATION_OUTSIDE_ALL_WINDOWS));
7876 ASSERT_TRUE(mDispatcher->waitForIdle());
7877 mFakePolicy->assertNotifyAnrWasNotCalled();
7878}
7879
7880// Since the focused window is paused, tapping on it should not produce any events
7881TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7882 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007883 mDispatcher->onWindowInfosChanged(
7884 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007885
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007886 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007887 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007888 FOCUSED_WINDOW_LOCATION));
7889
7890 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7891 ASSERT_TRUE(mDispatcher->waitForIdle());
7892 // Should not ANR because the window is paused, and touches shouldn't go to it
7893 mFakePolicy->assertNotifyAnrWasNotCalled();
7894
7895 mFocusedWindow->assertNoEvents();
7896 mUnfocusedWindow->assertNoEvents();
7897}
7898
7899/**
7900 * 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 -07007901 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007902 * If a different window becomes focused at this time, the key should go to that window instead.
7903 *
7904 * Warning!!!
7905 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7906 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007907 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007908 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7909 *
7910 * If that value changes, this test should also change.
7911 */
7912TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7913 // Set a long ANR timeout to prevent it from triggering
7914 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007915 mDispatcher->onWindowInfosChanged(
7916 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007917
7918 tapOnUnfocusedWindow();
7919 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7920 ASSERT_TRUE(downSequenceNum);
7921 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7922 ASSERT_TRUE(upSequenceNum);
7923 // Don't finish the events yet, and send a key
7924 // Injection will succeed because we will eventually give up and send the key to the focused
7925 // window even if motions are still being processed.
7926
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007927 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007928 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7929 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007931 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007932 // and the key remains pending, waiting for the touch events to be processed.
7933 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7934 // under the hood.
7935 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7936 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007937
7938 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007939 mFocusedWindow->setFocusable(false);
7940 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007941 mDispatcher->onWindowInfosChanged(
7942 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007943 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007944
7945 // Focus events should precede the key events
7946 mUnfocusedWindow->consumeFocusEvent(true);
7947 mFocusedWindow->consumeFocusEvent(false);
7948
7949 // Finish the tap events, which should unblock dispatcher
7950 mUnfocusedWindow->finishEvent(*downSequenceNum);
7951 mUnfocusedWindow->finishEvent(*upSequenceNum);
7952
7953 // Now that all queues are cleared and no backlog in the connections, the key event
7954 // can finally go to the newly focused "mUnfocusedWindow".
7955 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7956 mFocusedWindow->assertNoEvents();
7957 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007958 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007959}
7960
7961// When the touch stream is split across 2 windows, and one of them does not respond,
7962// then ANR should be raised and the touch should be canceled for the unresponsive window.
7963// The other window should not be affected by that.
7964TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7965 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007966 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7967 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7968 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007969 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007970 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007971
7972 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007973 mDispatcher->notifyMotion(
7974 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7975 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007976
7977 const std::chrono::duration timeout =
7978 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007979 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007980
7981 mUnfocusedWindow->consumeMotionDown();
7982 mFocusedWindow->consumeMotionDown();
7983 // Focused window may or may not receive ACTION_MOVE
7984 // But it should definitely receive ACTION_CANCEL due to the ANR
7985 InputEvent* event;
7986 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7987 ASSERT_TRUE(moveOrCancelSequenceNum);
7988 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7989 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007990 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007991 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7992 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7993 mFocusedWindow->consumeMotionCancel();
7994 } else {
7995 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7996 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007997 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007998 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7999 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008000
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008001 mUnfocusedWindow->assertNoEvents();
8002 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008003 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008004}
8005
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008006/**
8007 * If we have no focused window, and a key comes in, we start the ANR timer.
8008 * The focused application should add a focused window before the timer runs out to prevent ANR.
8009 *
8010 * If the user touches another application during this time, the key should be dropped.
8011 * Next, if a new focused window comes in, without toggling the focused application,
8012 * then no ANR should occur.
8013 *
8014 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8015 * but in some cases the policy may not update the focused application.
8016 */
8017TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8018 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8019 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008020 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008021 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8022 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8023 mFocusedWindow->setFocusable(false);
8024
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008025 mDispatcher->onWindowInfosChanged(
8026 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008027 mFocusedWindow->consumeFocusEvent(false);
8028
8029 // Send a key. The ANR timer should start because there is no focused window.
8030 // 'focusedApplication' will get blamed if this timer completes.
8031 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008032 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008033 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8034 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008035 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008037
8038 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8039 // then the injected touches won't cause the focused event to get dropped.
8040 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8041 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8042 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8043 // For this test, it means that the key would get delivered to the window once it becomes
8044 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008045 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008046
8047 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008048 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8049 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8050 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008051
8052 // We do not consume the motion right away, because that would require dispatcher to first
8053 // process (== drop) the key event, and by that time, ANR will be raised.
8054 // Set the focused window first.
8055 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008056 mDispatcher->onWindowInfosChanged(
8057 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008058 setFocusedWindow(mFocusedWindow);
8059 mFocusedWindow->consumeFocusEvent(true);
8060 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8061 // to another application. This could be a bug / behaviour in the policy.
8062
8063 mUnfocusedWindow->consumeMotionDown();
8064
8065 ASSERT_TRUE(mDispatcher->waitForIdle());
8066 // Should not ANR because we actually have a focused window. It was just added too slowly.
8067 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8068}
8069
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008070// These tests ensure we cannot send touch events to a window that's positioned behind a window
8071// that has feature NO_INPUT_CHANNEL.
8072// Layout:
8073// Top (closest to user)
8074// mNoInputWindow (above all windows)
8075// mBottomWindow
8076// Bottom (furthest from user)
8077class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8078 virtual void SetUp() override {
8079 InputDispatcherTest::SetUp();
8080
8081 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008082 mNoInputWindow =
8083 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8084 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008085 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008086 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008087 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8088 // It's perfectly valid for this window to not have an associated input channel
8089
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008090 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8091 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008092 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8093
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008094 mDispatcher->onWindowInfosChanged(
8095 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008096 }
8097
8098protected:
8099 std::shared_ptr<FakeApplicationHandle> mApplication;
8100 sp<FakeWindowHandle> mNoInputWindow;
8101 sp<FakeWindowHandle> mBottomWindow;
8102};
8103
8104TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8105 PointF touchedPoint = {10, 10};
8106
Prabir Pradhan678438e2023-04-13 19:32:51 +00008107 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8108 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8109 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008110
8111 mNoInputWindow->assertNoEvents();
8112 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8113 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8114 // and therefore should prevent mBottomWindow from receiving touches
8115 mBottomWindow->assertNoEvents();
8116}
8117
8118/**
8119 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8120 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8121 */
8122TEST_F(InputDispatcherMultiWindowOcclusionTests,
8123 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008124 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8125 "Window with input channel and NO_INPUT_CHANNEL",
8126 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008127
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008128 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008129 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008130 mDispatcher->onWindowInfosChanged(
8131 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008132
8133 PointF touchedPoint = {10, 10};
8134
Prabir Pradhan678438e2023-04-13 19:32:51 +00008135 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8136 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8137 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008138
8139 mNoInputWindow->assertNoEvents();
8140 mBottomWindow->assertNoEvents();
8141}
8142
Vishnu Nair958da932020-08-21 17:12:37 -07008143class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8144protected:
8145 std::shared_ptr<FakeApplicationHandle> mApp;
8146 sp<FakeWindowHandle> mWindow;
8147 sp<FakeWindowHandle> mMirror;
8148
8149 virtual void SetUp() override {
8150 InputDispatcherTest::SetUp();
8151 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008152 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8153 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8154 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008155 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8156 mWindow->setFocusable(true);
8157 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008158 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008159 }
8160};
8161
8162TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8163 // Request focus on a mirrored window
8164 setFocusedWindow(mMirror);
8165
8166 // window gets focused
8167 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008169 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008170 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8171}
8172
8173// A focused & mirrored window remains focused only if the window and its mirror are both
8174// focusable.
8175TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8176 setFocusedWindow(mMirror);
8177
8178 // window gets focused
8179 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008181 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008182 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008184 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008185 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8186
8187 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008188 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008189
8190 // window loses focus since one of the windows associated with the token in not focusable
8191 mWindow->consumeFocusEvent(false);
8192
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008193 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008194 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008195 mWindow->assertNoEvents();
8196}
8197
8198// A focused & mirrored window remains focused until the window and its mirror both become
8199// invisible.
8200TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8201 setFocusedWindow(mMirror);
8202
8203 // window gets focused
8204 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008206 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008207 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008209 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008210 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8211
8212 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008213 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008214
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008216 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008217 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008219 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008220 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8221
8222 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008223 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008224
8225 // window loses focus only after all windows associated with the token become invisible.
8226 mWindow->consumeFocusEvent(false);
8227
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008228 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008229 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008230 mWindow->assertNoEvents();
8231}
8232
8233// A focused & mirrored window remains focused until both windows are removed.
8234TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8235 setFocusedWindow(mMirror);
8236
8237 // window gets focused
8238 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008240 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008241 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008243 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008244 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8245
8246 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008247 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008248
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008250 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008251 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008253 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008254 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8255
8256 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008257 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008258 mWindow->consumeFocusEvent(false);
8259
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008260 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008261 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008262 mWindow->assertNoEvents();
8263}
8264
8265// Focus request can be pending until one window becomes visible.
8266TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8267 // Request focus on an invisible mirror.
8268 mWindow->setVisible(false);
8269 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008270 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008271 setFocusedWindow(mMirror);
8272
8273 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008275 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8276 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008277
8278 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008279 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008280
8281 // window gets focused
8282 mWindow->consumeFocusEvent(true);
8283 // window gets the pending key event
8284 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8285}
Prabir Pradhan99987712020-11-10 18:43:05 -08008286
8287class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8288protected:
8289 std::shared_ptr<FakeApplicationHandle> mApp;
8290 sp<FakeWindowHandle> mWindow;
8291 sp<FakeWindowHandle> mSecondWindow;
8292
8293 void SetUp() override {
8294 InputDispatcherTest::SetUp();
8295 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008296 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008297 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008298 mSecondWindow =
8299 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008300 mSecondWindow->setFocusable(true);
8301
8302 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008303 mDispatcher->onWindowInfosChanged(
8304 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008305
8306 setFocusedWindow(mWindow);
8307 mWindow->consumeFocusEvent(true);
8308 }
8309
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008310 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008311 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008312 }
8313
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008314 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8315 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008316 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008317 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8318 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008319 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008320 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008321 }
8322};
8323
8324TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8325 // Ensure that capture cannot be obtained for unfocused windows.
8326 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8327 mFakePolicy->assertSetPointerCaptureNotCalled();
8328 mSecondWindow->assertNoEvents();
8329
8330 // Ensure that capture can be enabled from the focus window.
8331 requestAndVerifyPointerCapture(mWindow, true);
8332
8333 // Ensure that capture cannot be disabled from a window that does not have capture.
8334 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8335 mFakePolicy->assertSetPointerCaptureNotCalled();
8336
8337 // Ensure that capture can be disabled from the window with capture.
8338 requestAndVerifyPointerCapture(mWindow, false);
8339}
8340
8341TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008342 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008343
8344 setFocusedWindow(mSecondWindow);
8345
8346 // Ensure that the capture disabled event was sent first.
8347 mWindow->consumeCaptureEvent(false);
8348 mWindow->consumeFocusEvent(false);
8349 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008350 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008351
8352 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008353 notifyPointerCaptureChanged({});
8354 notifyPointerCaptureChanged(request);
8355 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008356 mWindow->assertNoEvents();
8357 mSecondWindow->assertNoEvents();
8358 mFakePolicy->assertSetPointerCaptureNotCalled();
8359}
8360
8361TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008362 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008363
8364 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008365 notifyPointerCaptureChanged({});
8366 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008367
8368 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008369 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008370 mWindow->consumeCaptureEvent(false);
8371 mWindow->assertNoEvents();
8372}
8373
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008374TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8375 requestAndVerifyPointerCapture(mWindow, true);
8376
8377 // The first window loses focus.
8378 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008379 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008380 mWindow->consumeCaptureEvent(false);
8381
8382 // Request Pointer Capture from the second window before the notification from InputReader
8383 // arrives.
8384 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008385 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008386
8387 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008388 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008389
8390 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008391 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008392
8393 mSecondWindow->consumeFocusEvent(true);
8394 mSecondWindow->consumeCaptureEvent(true);
8395}
8396
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008397TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8398 // App repeatedly enables and disables capture.
8399 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8400 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8401 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8402 mFakePolicy->assertSetPointerCaptureCalled(false);
8403 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8404 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8405
8406 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8407 // first request is now stale, this should do nothing.
8408 notifyPointerCaptureChanged(firstRequest);
8409 mWindow->assertNoEvents();
8410
8411 // InputReader notifies that the second request was enabled.
8412 notifyPointerCaptureChanged(secondRequest);
8413 mWindow->consumeCaptureEvent(true);
8414}
8415
Prabir Pradhan7092e262022-05-03 16:51:09 +00008416TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8417 requestAndVerifyPointerCapture(mWindow, true);
8418
8419 // App toggles pointer capture off and on.
8420 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8421 mFakePolicy->assertSetPointerCaptureCalled(false);
8422
8423 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8424 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8425
8426 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8427 // preceding "disable" request.
8428 notifyPointerCaptureChanged(enableRequest);
8429
8430 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8431 // any notifications.
8432 mWindow->assertNoEvents();
8433}
8434
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008435/**
8436 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8437 * mouse movements don't affect the previous mouse hovering state.
8438 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8439 * HOVER_MOVE events).
8440 */
8441TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8442 // Mouse hover on the window
8443 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8444 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8445 .build());
8446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8447 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8448 .build());
8449
8450 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8451 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8452
8453 // Start pointer capture
8454 requestAndVerifyPointerCapture(mWindow, true);
8455
8456 // Send some relative mouse movements and receive them in the window.
8457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8458 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8459 .build());
8460 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8461 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8462
8463 // Stop pointer capture
8464 requestAndVerifyPointerCapture(mWindow, false);
8465
8466 // Continue hovering on the window
8467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8468 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8469 .build());
8470 mWindow->consumeMotionEvent(
8471 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8472
8473 mWindow->assertNoEvents();
8474}
8475
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008476class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8477protected:
8478 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008479
8480 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8481 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8482
8483 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8484 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8485
8486 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8487 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8488 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8489 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8490 MAXIMUM_OBSCURING_OPACITY);
8491
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008492 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8493 static constexpr gui::Uid APP_B_UID{10002};
8494 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008495
8496 sp<FakeWindowHandle> mTouchWindow;
8497
8498 virtual void SetUp() override {
8499 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008500 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008501 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8502 }
8503
8504 virtual void TearDown() override {
8505 InputDispatcherTest::TearDown();
8506 mTouchWindow.clear();
8507 }
8508
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008509 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008510 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008511 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008512 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008513 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008514 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008515 return window;
8516 }
8517
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008518 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008519 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8520 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008521 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008522 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008523 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008524 return window;
8525 }
8526
8527 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8529 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8530 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008531 }
8532};
8533
8534TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008535 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008536 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008537 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008538
8539 touch();
8540
8541 mTouchWindow->assertNoEvents();
8542}
8543
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008544TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008545 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8546 const sp<FakeWindowHandle>& w =
8547 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008548 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008549
8550 touch();
8551
8552 mTouchWindow->assertNoEvents();
8553}
8554
8555TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008556 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8557 const sp<FakeWindowHandle>& w =
8558 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008559 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008560
8561 touch();
8562
8563 w->assertNoEvents();
8564}
8565
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008566TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008567 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008568 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008569
8570 touch();
8571
8572 mTouchWindow->consumeAnyMotionDown();
8573}
8574
8575TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008576 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008577 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008578 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008579 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008580
8581 touch({PointF{100, 100}});
8582
8583 mTouchWindow->consumeAnyMotionDown();
8584}
8585
8586TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008587 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008588 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008589 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008590
8591 touch();
8592
8593 mTouchWindow->consumeAnyMotionDown();
8594}
8595
8596TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8597 const sp<FakeWindowHandle>& w =
8598 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008599 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008600
8601 touch();
8602
8603 mTouchWindow->consumeAnyMotionDown();
8604}
8605
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008606TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8607 const sp<FakeWindowHandle>& w =
8608 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008609 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008610
8611 touch();
8612
8613 w->assertNoEvents();
8614}
8615
8616/**
8617 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8618 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8619 * window, the occluding window will still receive ACTION_OUTSIDE event.
8620 */
8621TEST_F(InputDispatcherUntrustedTouchesTest,
8622 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8623 const sp<FakeWindowHandle>& w =
8624 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008625 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008626 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008627
8628 touch();
8629
8630 w->consumeMotionOutside();
8631}
8632
8633TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8634 const sp<FakeWindowHandle>& w =
8635 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008636 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008637 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008638
8639 touch();
8640
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008641 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008642}
8643
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008644TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008645 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008646 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8647 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008648 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008649
8650 touch();
8651
8652 mTouchWindow->consumeAnyMotionDown();
8653}
8654
8655TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8656 const sp<FakeWindowHandle>& w =
8657 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8658 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008659 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008660
8661 touch();
8662
8663 mTouchWindow->consumeAnyMotionDown();
8664}
8665
8666TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008667 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008668 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8669 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008670 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008671
8672 touch();
8673
8674 mTouchWindow->assertNoEvents();
8675}
8676
8677TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8678 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8679 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008680 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8681 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008682 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008683 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8684 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008685 mDispatcher->onWindowInfosChanged(
8686 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008687
8688 touch();
8689
8690 mTouchWindow->assertNoEvents();
8691}
8692
8693TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8694 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8695 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008696 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8697 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008698 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008699 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8700 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008701 mDispatcher->onWindowInfosChanged(
8702 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008703
8704 touch();
8705
8706 mTouchWindow->consumeAnyMotionDown();
8707}
8708
8709TEST_F(InputDispatcherUntrustedTouchesTest,
8710 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8711 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008712 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8713 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008714 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008715 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8716 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008717 mDispatcher->onWindowInfosChanged(
8718 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008719
8720 touch();
8721
8722 mTouchWindow->consumeAnyMotionDown();
8723}
8724
8725TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8726 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008727 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8728 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008729 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008730 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8731 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008732 mDispatcher->onWindowInfosChanged(
8733 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008734
8735 touch();
8736
8737 mTouchWindow->assertNoEvents();
8738}
8739
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008740TEST_F(InputDispatcherUntrustedTouchesTest,
8741 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8742 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008743 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8744 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008745 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008746 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8747 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008748 mDispatcher->onWindowInfosChanged(
8749 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008750
8751 touch();
8752
8753 mTouchWindow->assertNoEvents();
8754}
8755
8756TEST_F(InputDispatcherUntrustedTouchesTest,
8757 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8758 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008759 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8760 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008761 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008762 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8763 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008764 mDispatcher->onWindowInfosChanged(
8765 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008766
8767 touch();
8768
8769 mTouchWindow->consumeAnyMotionDown();
8770}
8771
8772TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8773 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008774 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8775 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008776 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008777
8778 touch();
8779
8780 mTouchWindow->consumeAnyMotionDown();
8781}
8782
8783TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8784 const sp<FakeWindowHandle>& w =
8785 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008786 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008787
8788 touch();
8789
8790 mTouchWindow->consumeAnyMotionDown();
8791}
8792
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008793TEST_F(InputDispatcherUntrustedTouchesTest,
8794 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8795 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8796 const sp<FakeWindowHandle>& w =
8797 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008798 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008799
8800 touch();
8801
8802 mTouchWindow->assertNoEvents();
8803}
8804
8805TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8806 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8807 const sp<FakeWindowHandle>& w =
8808 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008809 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008810
8811 touch();
8812
8813 mTouchWindow->consumeAnyMotionDown();
8814}
8815
8816TEST_F(InputDispatcherUntrustedTouchesTest,
8817 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8818 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8819 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008820 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8821 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008822 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008823
8824 touch();
8825
8826 mTouchWindow->consumeAnyMotionDown();
8827}
8828
8829TEST_F(InputDispatcherUntrustedTouchesTest,
8830 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8831 const sp<FakeWindowHandle>& w1 =
8832 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8833 OPACITY_BELOW_THRESHOLD);
8834 const sp<FakeWindowHandle>& w2 =
8835 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8836 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008837 mDispatcher->onWindowInfosChanged(
8838 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008839
8840 touch();
8841
8842 mTouchWindow->assertNoEvents();
8843}
8844
8845/**
8846 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8847 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8848 * (which alone would result in allowing touches) does not affect the blocking behavior.
8849 */
8850TEST_F(InputDispatcherUntrustedTouchesTest,
8851 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8852 const sp<FakeWindowHandle>& wB =
8853 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8854 OPACITY_BELOW_THRESHOLD);
8855 const sp<FakeWindowHandle>& wC =
8856 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8857 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008858 mDispatcher->onWindowInfosChanged(
8859 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008860
8861 touch();
8862
8863 mTouchWindow->assertNoEvents();
8864}
8865
8866/**
8867 * This test is testing that a window from a different UID but with same application token doesn't
8868 * block the touch. Apps can share the application token for close UI collaboration for example.
8869 */
8870TEST_F(InputDispatcherUntrustedTouchesTest,
8871 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8872 const sp<FakeWindowHandle>& w =
8873 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8874 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008875 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008876
8877 touch();
8878
8879 mTouchWindow->consumeAnyMotionDown();
8880}
8881
arthurhungb89ccb02020-12-30 16:19:01 +08008882class InputDispatcherDragTests : public InputDispatcherTest {
8883protected:
8884 std::shared_ptr<FakeApplicationHandle> mApp;
8885 sp<FakeWindowHandle> mWindow;
8886 sp<FakeWindowHandle> mSecondWindow;
8887 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008888 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008889 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8890 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008891
8892 void SetUp() override {
8893 InputDispatcherTest::SetUp();
8894 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008895 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008896 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008897
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008898 mSecondWindow =
8899 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008900 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008901
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008902 mSpyWindow =
8903 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008904 mSpyWindow->setSpy(true);
8905 mSpyWindow->setTrustedOverlay(true);
8906 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8907
arthurhungb89ccb02020-12-30 16:19:01 +08008908 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008909 mDispatcher->onWindowInfosChanged(
8910 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8911 {},
8912 0,
8913 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008914 }
8915
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008916 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8917 switch (fromSource) {
8918 case AINPUT_SOURCE_TOUCHSCREEN:
8919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008920 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008921 ADISPLAY_ID_DEFAULT, {50, 50}))
8922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8923 break;
8924 case AINPUT_SOURCE_STYLUS:
8925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008926 injectMotionEvent(*mDispatcher,
8927 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8928 AINPUT_SOURCE_STYLUS)
8929 .buttonState(
8930 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8931 .pointer(PointerBuilder(0, ToolType::STYLUS)
8932 .x(50)
8933 .y(50))
8934 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008935 break;
8936 case AINPUT_SOURCE_MOUSE:
8937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008938 injectMotionEvent(*mDispatcher,
8939 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8940 AINPUT_SOURCE_MOUSE)
8941 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8942 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8943 ToolType::MOUSE)
8944 .x(50)
8945 .y(50))
8946 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008947 break;
8948 default:
8949 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8950 }
arthurhungb89ccb02020-12-30 16:19:01 +08008951
8952 // Window should receive motion event.
8953 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008954 // Spy window should also receive motion event
8955 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008956 }
8957
8958 // Start performing drag, we will create a drag window and transfer touch to it.
8959 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8960 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008961 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008962 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008963 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008964 }
arthurhungb89ccb02020-12-30 16:19:01 +08008965
8966 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008967 mDragWindow =
8968 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008969 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008970 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8971 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8972 {},
8973 0,
8974 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008975
8976 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008977 bool transferred =
8978 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008979 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008980 if (transferred) {
8981 mWindow->consumeMotionCancel();
8982 mDragWindow->consumeMotionDown();
8983 }
8984 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008985 }
8986};
8987
8988TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008989 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008990
8991 // Move on window.
8992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008993 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008994 ADISPLAY_ID_DEFAULT, {50, 50}))
8995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8996 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8997 mWindow->consumeDragEvent(false, 50, 50);
8998 mSecondWindow->assertNoEvents();
8999
9000 // Move to another window.
9001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009002 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009003 ADISPLAY_ID_DEFAULT, {150, 50}))
9004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9005 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9006 mWindow->consumeDragEvent(true, 150, 50);
9007 mSecondWindow->consumeDragEvent(false, 50, 50);
9008
9009 // Move back to original window.
9010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009011 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009012 ADISPLAY_ID_DEFAULT, {50, 50}))
9013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9014 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9015 mWindow->consumeDragEvent(false, 50, 50);
9016 mSecondWindow->consumeDragEvent(true, -50, 50);
9017
9018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009019 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9020 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9022 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9023 mWindow->assertNoEvents();
9024 mSecondWindow->assertNoEvents();
9025}
9026
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009027TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009028 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009029
9030 // No cancel event after drag start
9031 mSpyWindow->assertNoEvents();
9032
9033 const MotionEvent secondFingerDownEvent =
9034 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009038 .build();
9039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009040 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009041 InputEventInjectionSync::WAIT_FOR_RESULT))
9042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9043
9044 // Receives cancel for first pointer after next pointer down
9045 mSpyWindow->consumeMotionCancel();
9046 mSpyWindow->consumeMotionDown();
9047
9048 mSpyWindow->assertNoEvents();
9049}
9050
arthurhungf452d0b2021-01-06 00:19:52 +08009051TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009052 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009053
9054 // Move on window.
9055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009056 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009057 ADISPLAY_ID_DEFAULT, {50, 50}))
9058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9059 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9060 mWindow->consumeDragEvent(false, 50, 50);
9061 mSecondWindow->assertNoEvents();
9062
9063 // Move to another window.
9064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009065 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009066 ADISPLAY_ID_DEFAULT, {150, 50}))
9067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9068 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9069 mWindow->consumeDragEvent(true, 150, 50);
9070 mSecondWindow->consumeDragEvent(false, 50, 50);
9071
9072 // drop to another window.
9073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009074 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009075 {150, 50}))
9076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9077 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009078 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009079 mWindow->assertNoEvents();
9080 mSecondWindow->assertNoEvents();
9081}
9082
arthurhung6d4bed92021-03-17 11:59:33 +08009083TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009084 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009085
9086 // Move on window and keep button pressed.
9087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009088 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009089 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9090 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009091 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009092 .build()))
9093 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9094 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9095 mWindow->consumeDragEvent(false, 50, 50);
9096 mSecondWindow->assertNoEvents();
9097
9098 // Move to another window and release button, expect to drop item.
9099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009100 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009101 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9102 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009103 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009104 .build()))
9105 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9106 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9107 mWindow->assertNoEvents();
9108 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009109 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009110
9111 // nothing to the window.
9112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009113 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009114 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9115 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009116 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009117 .build()))
9118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9119 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9120 mWindow->assertNoEvents();
9121 mSecondWindow->assertNoEvents();
9122}
9123
Arthur Hung54745652022-04-20 07:17:41 +00009124TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009125 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009126
9127 // Set second window invisible.
9128 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009129 mDispatcher->onWindowInfosChanged(
9130 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009131
9132 // Move on window.
9133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009134 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009135 ADISPLAY_ID_DEFAULT, {50, 50}))
9136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9137 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9138 mWindow->consumeDragEvent(false, 50, 50);
9139 mSecondWindow->assertNoEvents();
9140
9141 // Move to another window.
9142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009143 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009144 ADISPLAY_ID_DEFAULT, {150, 50}))
9145 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9146 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9147 mWindow->consumeDragEvent(true, 150, 50);
9148 mSecondWindow->assertNoEvents();
9149
9150 // drop to another window.
9151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009152 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009153 {150, 50}))
9154 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9155 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009156 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009157 mWindow->assertNoEvents();
9158 mSecondWindow->assertNoEvents();
9159}
9160
Arthur Hung54745652022-04-20 07:17:41 +00009161TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009162 // Ensure window could track pointerIds if it didn't support split touch.
9163 mWindow->setPreventSplitting(true);
9164
Arthur Hung54745652022-04-20 07:17:41 +00009165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009166 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009167 {50, 50}))
9168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9169 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9170
9171 const MotionEvent secondFingerDownEvent =
9172 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9173 .displayId(ADISPLAY_ID_DEFAULT)
9174 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009175 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9176 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009177 .build();
9178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009179 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009180 InputEventInjectionSync::WAIT_FOR_RESULT))
9181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009182 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009183
9184 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009185 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009186}
9187
9188TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9189 // First down on second window.
9190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009191 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009192 {150, 50}))
9193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9194
9195 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9196
9197 // Second down on first window.
9198 const MotionEvent secondFingerDownEvent =
9199 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9200 .displayId(ADISPLAY_ID_DEFAULT)
9201 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009202 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9203 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009204 .build();
9205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009206 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009207 InputEventInjectionSync::WAIT_FOR_RESULT))
9208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9209 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9210
9211 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009212 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009213
9214 // Move on window.
9215 const MotionEvent secondFingerMoveEvent =
9216 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9217 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009218 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9219 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009220 .build();
9221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009222 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009223 InputEventInjectionSync::WAIT_FOR_RESULT));
9224 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9225 mWindow->consumeDragEvent(false, 50, 50);
9226 mSecondWindow->consumeMotionMove();
9227
9228 // Release the drag pointer should perform drop.
9229 const MotionEvent secondFingerUpEvent =
9230 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9231 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009232 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9233 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009234 .build();
9235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009236 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009237 InputEventInjectionSync::WAIT_FOR_RESULT));
9238 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009239 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009240 mWindow->assertNoEvents();
9241 mSecondWindow->consumeMotionMove();
9242}
9243
Arthur Hung3915c1f2022-05-31 07:17:17 +00009244TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009245 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009246
9247 // Update window of second display.
9248 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009249 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009250 mDispatcher->onWindowInfosChanged(
9251 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9252 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9253 {},
9254 0,
9255 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009256
9257 // Let second display has a touch state.
9258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009259 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009260 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9261 AINPUT_SOURCE_TOUCHSCREEN)
9262 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009263 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009264 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009265 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009266 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009267 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009268 mDispatcher->onWindowInfosChanged(
9269 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9270 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9271 {},
9272 0,
9273 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009274
9275 // Move on window.
9276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009277 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009278 ADISPLAY_ID_DEFAULT, {50, 50}))
9279 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9280 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9281 mWindow->consumeDragEvent(false, 50, 50);
9282 mSecondWindow->assertNoEvents();
9283
9284 // Move to another window.
9285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009286 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009287 ADISPLAY_ID_DEFAULT, {150, 50}))
9288 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9289 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9290 mWindow->consumeDragEvent(true, 150, 50);
9291 mSecondWindow->consumeDragEvent(false, 50, 50);
9292
9293 // drop to another window.
9294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009295 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009296 {150, 50}))
9297 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9298 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009299 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009300 mWindow->assertNoEvents();
9301 mSecondWindow->assertNoEvents();
9302}
9303
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009304TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9305 startDrag(true, AINPUT_SOURCE_MOUSE);
9306 // Move on window.
9307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009308 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009309 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9310 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009311 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009312 .x(50)
9313 .y(50))
9314 .build()))
9315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9316 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9317 mWindow->consumeDragEvent(false, 50, 50);
9318 mSecondWindow->assertNoEvents();
9319
9320 // Move to another window.
9321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009322 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009323 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9324 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009325 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009326 .x(150)
9327 .y(50))
9328 .build()))
9329 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9330 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9331 mWindow->consumeDragEvent(true, 150, 50);
9332 mSecondWindow->consumeDragEvent(false, 50, 50);
9333
9334 // drop to another window.
9335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009336 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009337 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9338 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009339 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009340 .x(150)
9341 .y(50))
9342 .build()))
9343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9344 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009345 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009346 mWindow->assertNoEvents();
9347 mSecondWindow->assertNoEvents();
9348}
9349
Linnan Li5af92f92023-07-14 14:36:22 +08009350/**
9351 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9352 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9353 */
9354TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9355 // Down on second window
9356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9357 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9358 {150, 50}))
9359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9360
9361 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9362 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9363
9364 // Down on first window
9365 const MotionEvent secondFingerDownEvent =
9366 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9367 .displayId(ADISPLAY_ID_DEFAULT)
9368 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9369 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9370 .build();
9371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9372 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9373 InputEventInjectionSync::WAIT_FOR_RESULT))
9374 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9375 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9376 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9377 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9378
9379 // Start drag on first window
9380 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9381
9382 // Trigger cancel
9383 mDispatcher->cancelCurrentTouch();
9384 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9385 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9386 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9387
9388 ASSERT_TRUE(mDispatcher->waitForIdle());
9389 // The D&D finished with nullptr
9390 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9391
9392 // Remove drag window
9393 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9394
9395 // Inject a simple gesture, ensure dispatcher not crashed
9396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9397 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9398 PointF{50, 50}))
9399 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9400 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9401
9402 const MotionEvent moveEvent =
9403 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9404 .displayId(ADISPLAY_ID_DEFAULT)
9405 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9406 .build();
9407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9408 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9409 InputEventInjectionSync::WAIT_FOR_RESULT))
9410 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9411 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9412
9413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9414 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9415 {50, 50}))
9416 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9417 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9418}
9419
Vishnu Nair062a8672021-09-03 16:07:44 -07009420class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9421
9422TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009424 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9425 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009426 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009427 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9428 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009429 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009430 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009431 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009432
9433 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009434 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009435 window->assertNoEvents();
9436
Prabir Pradhan678438e2023-04-13 19:32:51 +00009437 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9438 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009439 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9440 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009441 window->assertNoEvents();
9442
9443 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009444 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009445 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009446
Prabir Pradhan678438e2023-04-13 19:32:51 +00009447 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009448 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9449
Prabir Pradhan678438e2023-04-13 19:32:51 +00009450 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9451 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009452 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9453 window->assertNoEvents();
9454}
9455
9456TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9457 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9458 std::make_shared<FakeApplicationHandle>();
9459 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009460 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9461 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009462 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009463 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009464 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009466 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9467 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009468 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009469 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009470 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9471 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009472 mDispatcher->onWindowInfosChanged(
9473 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009474 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009475 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009476
9477 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009478 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009479 window->assertNoEvents();
9480
Prabir Pradhan678438e2023-04-13 19:32:51 +00009481 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9482 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009483 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9484 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009485 window->assertNoEvents();
9486
9487 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009488 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009489 mDispatcher->onWindowInfosChanged(
9490 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009491
Prabir Pradhan678438e2023-04-13 19:32:51 +00009492 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009493 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9494
Prabir Pradhan678438e2023-04-13 19:32:51 +00009495 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9496 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009497 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9498 window->assertNoEvents();
9499}
9500
9501TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9502 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9503 std::make_shared<FakeApplicationHandle>();
9504 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009505 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9506 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009507 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009508 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009509 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009510 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009511 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9512 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009513 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009514 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009515 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9516 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009517 mDispatcher->onWindowInfosChanged(
9518 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009519 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009520 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009521
9522 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009523 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009524 window->assertNoEvents();
9525
Prabir Pradhan678438e2023-04-13 19:32:51 +00009526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9529 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009530 window->assertNoEvents();
9531
9532 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009533 mDispatcher->onWindowInfosChanged(
9534 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009535
Prabir Pradhan678438e2023-04-13 19:32:51 +00009536 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009537 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9538
Prabir Pradhan678438e2023-04-13 19:32:51 +00009539 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9540 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009541 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9542 window->assertNoEvents();
9543}
9544
Antonio Kantekf16f2832021-09-28 04:39:20 +00009545class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9546protected:
9547 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009548 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009549 sp<FakeWindowHandle> mWindow;
9550 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009551 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009552
9553 void SetUp() override {
9554 InputDispatcherTest::SetUp();
9555
9556 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009557 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009558 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009559 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009560 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009561 mSecondWindow =
9562 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009563 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009564 mThirdWindow =
9565 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9566 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9567 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009568
9569 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009570 mDispatcher->onWindowInfosChanged(
9571 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9572 {},
9573 0,
9574 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009575 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009576 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009577
Antonio Kantek15beb512022-06-13 22:35:41 +00009578 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009579 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009580 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009581 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9582 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009583 mThirdWindow->assertNoEvents();
9584 }
9585
9586 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9587 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009588 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009589 SECOND_DISPLAY_ID)) {
9590 mWindow->assertNoEvents();
9591 mSecondWindow->assertNoEvents();
9592 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009593 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009594 }
9595
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009596 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009597 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009598 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9599 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009600 mWindow->consumeTouchModeEvent(inTouchMode);
9601 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009602 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009603 }
9604};
9605
Antonio Kantek26defcf2022-02-08 01:12:27 +00009606TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009607 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009608 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9609 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009610 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009611}
9612
Antonio Kantek26defcf2022-02-08 01:12:27 +00009613TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9614 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009615 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009616 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009617 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009618 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009619 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009620 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009621 mWindow->assertNoEvents();
9622 mSecondWindow->assertNoEvents();
9623}
9624
9625TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9626 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009627 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009628 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009629 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009630 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009631 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009632}
9633
Antonio Kantekf16f2832021-09-28 04:39:20 +00009634TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009635 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009636 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9637 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009638 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009639 mWindow->assertNoEvents();
9640 mSecondWindow->assertNoEvents();
9641}
9642
Antonio Kantek15beb512022-06-13 22:35:41 +00009643TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9644 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9645 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9646 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009647 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009648 mWindow->assertNoEvents();
9649 mSecondWindow->assertNoEvents();
9650 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9651}
9652
Antonio Kantek48710e42022-03-24 14:19:30 -07009653TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9654 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9656 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009657 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9658 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9659
9660 // Then remove focus.
9661 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009662 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009663
9664 // Assert that caller can switch touch mode by owning one of the last interacted window.
9665 const WindowInfo& windowInfo = *mWindow->getInfo();
9666 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9667 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009668 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009669}
9670
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009671class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9672public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009673 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009674 std::shared_ptr<FakeApplicationHandle> application =
9675 std::make_shared<FakeApplicationHandle>();
9676 std::string name = "Fake Spy ";
9677 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009678 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9679 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009680 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009681 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009682 return spy;
9683 }
9684
9685 sp<FakeWindowHandle> createForeground() {
9686 std::shared_ptr<FakeApplicationHandle> application =
9687 std::make_shared<FakeApplicationHandle>();
9688 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009689 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9690 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009691 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009692 return window;
9693 }
9694
9695private:
9696 int mSpyCount{0};
9697};
9698
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009699using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009700/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009701 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9702 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009703TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009704 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009705 ScopedSilentDeath _silentDeath;
9706
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009707 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009708 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009709 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009710 ".* not a trusted overlay");
9711}
9712
9713/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009714 * Input injection into a display with a spy window but no foreground windows should succeed.
9715 */
9716TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009717 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009718 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009719
9720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9723 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9724}
9725
9726/**
9727 * Verify the order in which different input windows receive events. The touched foreground window
9728 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9729 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9730 * receive events before ones belows it.
9731 *
9732 * Here, we set up a scenario with four windows in the following Z order from the top:
9733 * spy1, spy2, window, spy3.
9734 * We then inject an event and verify that the foreground "window" receives it first, followed by
9735 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9736 * window.
9737 */
9738TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9739 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009740 auto spy1 = createSpy();
9741 auto spy2 = createSpy();
9742 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009743 mDispatcher->onWindowInfosChanged(
9744 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009745 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9746 const size_t numChannels = channels.size();
9747
Michael Wright8e9a8562022-02-09 13:44:29 +00009748 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009749 if (!epollFd.ok()) {
9750 FAIL() << "Failed to create epoll fd";
9751 }
9752
9753 for (size_t i = 0; i < numChannels; i++) {
9754 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9755 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9756 FAIL() << "Failed to add fd to epoll";
9757 }
9758 }
9759
9760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009761 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9763
9764 std::vector<size_t> eventOrder;
9765 std::vector<struct epoll_event> events(numChannels);
9766 for (;;) {
9767 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9768 (100ms).count());
9769 if (nFds < 0) {
9770 FAIL() << "Failed to call epoll_wait";
9771 }
9772 if (nFds == 0) {
9773 break; // epoll_wait timed out
9774 }
9775 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009776 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009777 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009778 channels[i]->consumeMotionDown();
9779 }
9780 }
9781
9782 // Verify the order in which the events were received.
9783 EXPECT_EQ(3u, eventOrder.size());
9784 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9785 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9786 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9787}
9788
9789/**
9790 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9791 */
9792TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9793 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009794 auto spy = createSpy();
9795 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009796 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009797
9798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009799 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9801 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9802 spy->assertNoEvents();
9803}
9804
9805/**
9806 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9807 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9808 * to the window.
9809 */
9810TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9811 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009812 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009813 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009814 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009815
9816 // Inject an event outside the spy window's touchable region.
9817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009818 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9820 window->consumeMotionDown();
9821 spy->assertNoEvents();
9822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009823 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009824 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9825 window->consumeMotionUp();
9826 spy->assertNoEvents();
9827
9828 // Inject an event inside the spy window's touchable region.
9829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009830 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009831 {5, 10}))
9832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9833 window->consumeMotionDown();
9834 spy->consumeMotionDown();
9835}
9836
9837/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009838 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009839 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009840 */
9841TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9842 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009843 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009844 auto spy = createSpy();
9845 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009846 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009847 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009848 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009849
9850 // Inject an event outside the spy window's frame and touchable region.
9851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009853 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9855 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009856 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009857}
9858
9859/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009860 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9861 * pointers that are down within its bounds.
9862 */
9863TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9864 auto windowLeft = createForeground();
9865 windowLeft->setFrame({0, 0, 100, 200});
9866 auto windowRight = createForeground();
9867 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009868 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009869 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009870 mDispatcher->onWindowInfosChanged(
9871 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009872
9873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009874 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009875 {50, 50}))
9876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9877 windowLeft->consumeMotionDown();
9878 spy->consumeMotionDown();
9879
9880 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009881 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009882 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009883 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9884 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009885 .build();
9886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009887 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009888 InputEventInjectionSync::WAIT_FOR_RESULT))
9889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9890 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009891 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009892}
9893
9894/**
9895 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9896 * the spy should receive the second pointer with ACTION_DOWN.
9897 */
9898TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9899 auto window = createForeground();
9900 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009901 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009902 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009903 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009904
9905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009906 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009907 {50, 50}))
9908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9909 window->consumeMotionDown();
9910 spyRight->assertNoEvents();
9911
9912 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009913 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009914 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009915 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9916 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009917 .build();
9918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009919 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009920 InputEventInjectionSync::WAIT_FOR_RESULT))
9921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009922 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009923 spyRight->consumeMotionDown();
9924}
9925
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009926/**
9927 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9928 * windows should be allowed to control split touch.
9929 */
9930TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009931 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009932 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009933 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009934 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009935
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009936 auto window = createForeground();
9937 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009938
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009939 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009940
9941 // First finger down, no window touched.
9942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009943 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009944 {100, 200}))
9945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9946 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9947 window->assertNoEvents();
9948
9949 // Second finger down on window, the window should receive touch down.
9950 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009951 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009952 .displayId(ADISPLAY_ID_DEFAULT)
9953 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009954 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9955 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009956 .build();
9957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009958 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009959 InputEventInjectionSync::WAIT_FOR_RESULT))
9960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9961
9962 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009963 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009964}
9965
9966/**
9967 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9968 * do not receive key events.
9969 */
9970TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009971 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009972 spy->setFocusable(false);
9973
9974 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009975 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009976 setFocusedWindow(window);
9977 window->consumeFocusEvent(true);
9978
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009980 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9981 window->consumeKeyDown(ADISPLAY_ID_NONE);
9982
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009984 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9985 window->consumeKeyUp(ADISPLAY_ID_NONE);
9986
9987 spy->assertNoEvents();
9988}
9989
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009990using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9991
9992/**
9993 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9994 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9995 */
9996TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9997 auto window = createForeground();
9998 auto spy1 = createSpy();
9999 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010000 mDispatcher->onWindowInfosChanged(
10001 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010002
10003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010004 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10006 window->consumeMotionDown();
10007 spy1->consumeMotionDown();
10008 spy2->consumeMotionDown();
10009
10010 // Pilfer pointers from the second spy window.
10011 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10012 spy2->assertNoEvents();
10013 spy1->consumeMotionCancel();
10014 window->consumeMotionCancel();
10015
10016 // The rest of the gesture should only be sent to the second spy window.
10017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010018 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010019 ADISPLAY_ID_DEFAULT))
10020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10021 spy2->consumeMotionMove();
10022 spy1->assertNoEvents();
10023 window->assertNoEvents();
10024}
10025
10026/**
10027 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10028 * in the middle of the gesture.
10029 */
10030TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10031 auto window = createForeground();
10032 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010033 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010034
10035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010036 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10038 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10039 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10040
10041 window->releaseChannel();
10042
10043 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10044
10045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010046 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10048 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10049}
10050
10051/**
10052 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10053 * the spy, but not to any other windows.
10054 */
10055TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10056 auto spy = createSpy();
10057 auto window = createForeground();
10058
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010059 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010060
10061 // First finger down on the window and the spy.
10062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010063 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010064 {100, 200}))
10065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10066 spy->consumeMotionDown();
10067 window->consumeMotionDown();
10068
10069 // Spy window pilfers the pointers.
10070 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10071 window->consumeMotionCancel();
10072
10073 // Second finger down on the window and spy, but the window should not receive the pointer down.
10074 const MotionEvent secondFingerDownEvent =
10075 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10076 .displayId(ADISPLAY_ID_DEFAULT)
10077 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010078 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10079 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010080 .build();
10081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010082 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010083 InputEventInjectionSync::WAIT_FOR_RESULT))
10084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10085
Harry Cutts33476232023-01-30 19:57:29 +000010086 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010087
10088 // Third finger goes down outside all windows, so injection should fail.
10089 const MotionEvent thirdFingerDownEvent =
10090 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10091 .displayId(ADISPLAY_ID_DEFAULT)
10092 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010093 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10094 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10095 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010096 .build();
10097 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010098 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010099 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010100 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010101
10102 spy->assertNoEvents();
10103 window->assertNoEvents();
10104}
10105
10106/**
10107 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10108 */
10109TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10110 auto spy = createSpy();
10111 spy->setFrame(Rect(0, 0, 100, 100));
10112 auto window = createForeground();
10113 window->setFrame(Rect(0, 0, 200, 200));
10114
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010115 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010116
10117 // First finger down on the window only
10118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010119 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010120 {150, 150}))
10121 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10122 window->consumeMotionDown();
10123
10124 // Second finger down on the spy and window
10125 const MotionEvent secondFingerDownEvent =
10126 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10127 .displayId(ADISPLAY_ID_DEFAULT)
10128 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010129 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10130 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010131 .build();
10132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010133 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010134 InputEventInjectionSync::WAIT_FOR_RESULT))
10135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10136 spy->consumeMotionDown();
10137 window->consumeMotionPointerDown(1);
10138
10139 // Third finger down on the spy and window
10140 const MotionEvent thirdFingerDownEvent =
10141 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10142 .displayId(ADISPLAY_ID_DEFAULT)
10143 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010144 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10145 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10146 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010147 .build();
10148 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010149 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010150 InputEventInjectionSync::WAIT_FOR_RESULT))
10151 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10152 spy->consumeMotionPointerDown(1);
10153 window->consumeMotionPointerDown(2);
10154
10155 // Spy window pilfers the pointers.
10156 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010157 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10158 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010159
10160 spy->assertNoEvents();
10161 window->assertNoEvents();
10162}
10163
10164/**
10165 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10166 * other windows should be canceled. If this results in the cancellation of all pointers for some
10167 * window, then that window should receive ACTION_CANCEL.
10168 */
10169TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10170 auto spy = createSpy();
10171 spy->setFrame(Rect(0, 0, 100, 100));
10172 auto window = createForeground();
10173 window->setFrame(Rect(0, 0, 200, 200));
10174
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010175 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010176
10177 // First finger down on both spy and window
10178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010179 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010180 {10, 10}))
10181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10182 window->consumeMotionDown();
10183 spy->consumeMotionDown();
10184
10185 // Second finger down on the spy and window
10186 const MotionEvent secondFingerDownEvent =
10187 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10188 .displayId(ADISPLAY_ID_DEFAULT)
10189 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010190 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10191 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010192 .build();
10193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010194 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010195 InputEventInjectionSync::WAIT_FOR_RESULT))
10196 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10197 spy->consumeMotionPointerDown(1);
10198 window->consumeMotionPointerDown(1);
10199
10200 // Spy window pilfers the pointers.
10201 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10202 window->consumeMotionCancel();
10203
10204 spy->assertNoEvents();
10205 window->assertNoEvents();
10206}
10207
10208/**
10209 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10210 * be sent to other windows
10211 */
10212TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10213 auto spy = createSpy();
10214 spy->setFrame(Rect(0, 0, 100, 100));
10215 auto window = createForeground();
10216 window->setFrame(Rect(0, 0, 200, 200));
10217
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010218 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010219
10220 // First finger down on both window and spy
10221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010222 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010223 {10, 10}))
10224 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10225 window->consumeMotionDown();
10226 spy->consumeMotionDown();
10227
10228 // Spy window pilfers the pointers.
10229 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10230 window->consumeMotionCancel();
10231
10232 // Second finger down on the window only
10233 const MotionEvent secondFingerDownEvent =
10234 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10235 .displayId(ADISPLAY_ID_DEFAULT)
10236 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010237 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10238 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010239 .build();
10240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010241 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010242 InputEventInjectionSync::WAIT_FOR_RESULT))
10243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10244 window->consumeMotionDown();
10245 window->assertNoEvents();
10246
10247 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10248 spy->consumeMotionMove();
10249 spy->assertNoEvents();
10250}
10251
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010252/**
10253 * A window on the left and a window on the right. Also, a spy window that's above all of the
10254 * windows, and spanning both left and right windows.
10255 * Send simultaneous motion streams from two different devices, one to the left window, and another
10256 * to the right window.
10257 * Pilfer from spy window.
10258 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10259 */
10260TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10261 sp<FakeWindowHandle> spy = createSpy();
10262 spy->setFrame(Rect(0, 0, 200, 200));
10263 sp<FakeWindowHandle> leftWindow = createForeground();
10264 leftWindow->setFrame(Rect(0, 0, 100, 100));
10265
10266 sp<FakeWindowHandle> rightWindow = createForeground();
10267 rightWindow->setFrame(Rect(100, 0, 200, 100));
10268
10269 constexpr int32_t stylusDeviceId = 1;
10270 constexpr int32_t touchDeviceId = 2;
10271
10272 mDispatcher->onWindowInfosChanged(
10273 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10274
10275 // Stylus down on left window and spy
10276 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10277 .deviceId(stylusDeviceId)
10278 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10279 .build());
10280 leftWindow->consumeMotionEvent(
10281 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10282 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10283
10284 // Finger down on right window and spy - but spy already has stylus
10285 mDispatcher->notifyMotion(
10286 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10287 .deviceId(touchDeviceId)
10288 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10289 .build());
10290 rightWindow->consumeMotionEvent(
10291 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10292 leftWindow->consumeMotionEvent(
10293 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10294 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10295 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10296
10297 // Act: pilfer from spy. Spy is currently receiving touch events.
10298 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10299 rightWindow->consumeMotionEvent(
10300 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10301
10302 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10303 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10304 .deviceId(stylusDeviceId)
10305 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10306 .build());
10307 mDispatcher->notifyMotion(
10308 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10309 .deviceId(touchDeviceId)
10310 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10311 .build());
10312 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10313
10314 spy->assertNoEvents();
10315 leftWindow->assertNoEvents();
10316 rightWindow->assertNoEvents();
10317}
10318
Prabir Pradhand65552b2021-10-07 11:23:50 -070010319class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10320public:
10321 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10322 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10323 std::make_shared<FakeApplicationHandle>();
10324 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010325 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10326 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010327 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010328 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010329 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010330 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010331 overlay->setTrustedOverlay(true);
10332
10333 std::shared_ptr<FakeApplicationHandle> application =
10334 std::make_shared<FakeApplicationHandle>();
10335 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010336 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10337 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010338 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010339 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010340
10341 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010342 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010343 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010344 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010345 return {std::move(overlay), std::move(window)};
10346 }
10347
10348 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010349 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010350 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010351 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010352 }
10353
10354 void sendStylusEvent(int32_t action) {
10355 NotifyMotionArgs motionArgs =
10356 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10357 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010358 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010359 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010360 }
10361};
10362
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010363using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10364
10365TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010366 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010367 ScopedSilentDeath _silentDeath;
10368
Prabir Pradhand65552b2021-10-07 11:23:50 -070010369 auto [overlay, window] = setupStylusOverlayScenario();
10370 overlay->setTrustedOverlay(false);
10371 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010372 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10373 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010374 ".* not a trusted overlay");
10375}
10376
10377TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10378 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010379 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010380
10381 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10382 overlay->consumeMotionDown();
10383 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10384 overlay->consumeMotionUp();
10385
10386 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10387 window->consumeMotionDown();
10388 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10389 window->consumeMotionUp();
10390
10391 overlay->assertNoEvents();
10392 window->assertNoEvents();
10393}
10394
10395TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10396 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010397 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010398 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010399
10400 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10401 overlay->consumeMotionDown();
10402 window->consumeMotionDown();
10403 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10404 overlay->consumeMotionUp();
10405 window->consumeMotionUp();
10406
10407 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10408 window->consumeMotionDown();
10409 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10410 window->consumeMotionUp();
10411
10412 overlay->assertNoEvents();
10413 window->assertNoEvents();
10414}
10415
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010416/**
10417 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10418 * The scenario is as follows:
10419 * - The stylus interceptor overlay is configured as a spy window.
10420 * - The stylus interceptor spy receives the start of a new stylus gesture.
10421 * - It pilfers pointers and then configures itself to no longer be a spy.
10422 * - The stylus interceptor continues to receive the rest of the gesture.
10423 */
10424TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10425 auto [overlay, window] = setupStylusOverlayScenario();
10426 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010427 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010428
10429 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10430 overlay->consumeMotionDown();
10431 window->consumeMotionDown();
10432
10433 // The interceptor pilfers the pointers.
10434 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10435 window->consumeMotionCancel();
10436
10437 // The interceptor configures itself so that it is no longer a spy.
10438 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010439 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010440
10441 // It continues to receive the rest of the stylus gesture.
10442 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10443 overlay->consumeMotionMove();
10444 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10445 overlay->consumeMotionUp();
10446
10447 window->assertNoEvents();
10448}
10449
Prabir Pradhan5735a322022-04-11 17:23:34 +000010450struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010451 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010452 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010453 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10454 std::unique_ptr<InputDispatcher>& mDispatcher;
10455
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010456 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010457 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10458
10459 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010460 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010461 ADISPLAY_ID_DEFAULT, {100, 200},
10462 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10463 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10464 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10465 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10466 }
10467
10468 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010469 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010470 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010471 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010472 mPolicyFlags);
10473 }
10474
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010475 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010476 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10477 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010478 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10479 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010480 window->setOwnerInfo(mPid, mUid);
10481 return window;
10482 }
10483};
10484
10485using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10486
10487TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010488 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010489 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010490 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010491
10492 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10493 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10494 window->consumeMotionDown();
10495
10496 setFocusedWindow(window);
10497 window->consumeFocusEvent(true);
10498
10499 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10500 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10501 window->consumeKeyDown(ADISPLAY_ID_NONE);
10502}
10503
10504TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010505 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010506 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010507 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010508
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010509 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010510 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10511 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10512
10513 setFocusedWindow(window);
10514 window->consumeFocusEvent(true);
10515
10516 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10517 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10518 window->assertNoEvents();
10519}
10520
10521TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010522 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010523 auto window = owner.createWindow("Owned window");
10524 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010525 spy->setSpy(true);
10526 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010527 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010528
10529 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10530 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10531 spy->consumeMotionDown();
10532 window->consumeMotionDown();
10533}
10534
10535TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010536 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010537 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010538
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010539 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010540 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010541 randosSpy->setSpy(true);
10542 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010543 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010544
10545 // The event is targeted at owner's window, so injection should succeed, but the spy should
10546 // not receive the event.
10547 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10548 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10549 randosSpy->assertNoEvents();
10550 window->consumeMotionDown();
10551}
10552
10553TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010554 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010555 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010556
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010557 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010558 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010559 randosSpy->setSpy(true);
10560 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010561 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010562
10563 // A user that has injection permission can inject into any window.
10564 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010565 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010566 ADISPLAY_ID_DEFAULT));
10567 randosSpy->consumeMotionDown();
10568 window->consumeMotionDown();
10569
10570 setFocusedWindow(randosSpy);
10571 randosSpy->consumeFocusEvent(true);
10572
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010573 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010574 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10575 window->assertNoEvents();
10576}
10577
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010578TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010579 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010580 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010581
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010582 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010583 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010584 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10585 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010586 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010587
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010588 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010589 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10590 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10591 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010592 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010593}
10594
Garfield Tane84e6f92019-08-29 17:28:41 -070010595} // namespace android::inputdispatcher