blob: 2f63b2a6d06f40998379cf9c5b759cb8e84e23b8 [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>
Ameer Armalycff4fa52023-10-04 23:45:11 +000027#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000028#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080030#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080031#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070033#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080035#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080038#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070039#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080040#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080041#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050044using android::gui::FocusRequest;
45using android::gui::TouchOcclusionMode;
46using android::gui::WindowInfo;
47using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080048using android::os::InputEventInjectionResult;
49using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080050
Garfield Tane84e6f92019-08-29 17:28:41 -070051namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
Dominik Laskowski2f01d772022-03-23 16:01:29 -070053using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080054using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070056namespace {
57
Michael Wrightd02c5b62014-02-10 15:10:22 -080058// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000059static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080060
61// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000062static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080063static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
Jeff Brownf086ddb2014-02-11 14:28:48 -080065// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000066static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
67static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080068
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000069// Ensure common actions are interchangeable between keys and motions for convenience.
70static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
71static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080072static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
73static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
74static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
75static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070076static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080077static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070078static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080079static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080080static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081/**
82 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
83 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
84 * index 0) is the new pointer going down. The same pointer could have been placed at a different
85 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
86 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
87 * pointer id=0 leaves but the pointer id=1 remains.
88 */
89static constexpr int32_t POINTER_0_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080091static constexpr int32_t POINTER_1_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000093static constexpr int32_t POINTER_2_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000095static constexpr int32_t POINTER_3_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000097static constexpr int32_t POINTER_0_UP =
98 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080099static constexpr int32_t POINTER_1_UP =
100 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000101static constexpr int32_t POINTER_2_UP =
102 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800103
Antonio Kantek15beb512022-06-13 22:35:41 +0000104// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000105static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000106static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000107
Antonio Kantek15beb512022-06-13 22:35:41 +0000108// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000109static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000110static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000111
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000112// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000113static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000114
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800115static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
116
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700117/**
118 * If we expect to receive the event, the timeout can be made very long. When the test are running
119 * correctly, we will actually never wait until the end of the timeout because the wait will end
120 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
121 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
122 * developer can see the failure quickly (on human scale).
123 */
124static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
125/**
126 * When no event is expected, we can have a very short timeout. A large value here would slow down
127 * the tests. In the unlikely event of system being too slow, the event may still be present but the
128 * timeout would complete before it is consumed. This would result in test flakiness. If this
129 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
130 * would get noticed and addressed quickly.
131 */
132static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
133
Arthur Hungc539dbb2022-12-08 07:45:36 +0000134static constexpr int expectedWallpaperFlags =
135 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
136
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800137using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
138
Gang Wang342c9272020-01-13 13:15:04 -0500139/**
140 * Return a DOWN key event with KEYCODE_A.
141 */
142static KeyEvent getTestKeyEvent() {
143 KeyEvent event;
144
Garfield Tanfbe732e2020-01-24 11:26:14 -0800145 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
146 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
147 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500148 return event;
149}
150
Michael Wrightd02c5b62014-02-10 15:10:22 -0800151// --- FakeInputDispatcherPolicy ---
152
153class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000154 struct AnrResult {
155 sp<IBinder> token{};
156 gui::Pid pid{gui::Pid::INVALID};
157 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800158
Michael Wrightd02c5b62014-02-10 15:10:22 -0800159public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000160 FakeInputDispatcherPolicy() = default;
161 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800162
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800163 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700164 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700165 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700166 EXPECT_EQ(event.getDisplayId(), args.displayId);
167
168 const auto& keyEvent = static_cast<const KeyEvent&>(event);
169 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
170 EXPECT_EQ(keyEvent.getAction(), args.action);
171 });
Jackal Guof9696682018-10-05 12:23:23 +0800172 }
173
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700174 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
175 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700176 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700177 EXPECT_EQ(event.getDisplayId(), args.displayId);
178
179 const auto& motionEvent = static_cast<const MotionEvent&>(event);
180 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
181 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000182 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
183 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700186 });
Jackal Guof9696682018-10-05 12:23:23 +0800187 }
188
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700189 void assertFilterInputEventWasNotCalled() {
190 std::scoped_lock lock(mLock);
191 ASSERT_EQ(nullptr, mFilteredEvent);
192 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700195 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800196 ASSERT_TRUE(mConfigurationChangedTime)
197 << "Timed out waiting for configuration changed call";
198 ASSERT_EQ(*mConfigurationChangedTime, when);
199 mConfigurationChangedTime = std::nullopt;
200 }
201
202 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700203 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800204 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800205 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800206 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
207 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
208 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
209 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
210 mLastNotifySwitch = std::nullopt;
211 }
212
chaviwfd6d3512019-03-25 13:23:49 -0700213 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700214 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800215 ASSERT_EQ(touchedToken, mOnPointerDownToken);
216 mOnPointerDownToken.clear();
217 }
218
219 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700220 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800221 ASSERT_TRUE(mOnPointerDownToken == nullptr)
222 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700223 }
224
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700225 // This function must be called soon after the expected ANR timer starts,
226 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500227 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700228 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500229 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800230 std::unique_lock lock(mLock);
231 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500232 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800233 ASSERT_NO_FATAL_FAILURE(
234 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500235 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700236 }
237
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000238 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800239 const sp<WindowInfoHandle>& window) {
240 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
241 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
242 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500243 }
244
Prabir Pradhanedd96402022-02-15 01:46:16 -0800245 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
246 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000247 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800248 std::unique_lock lock(mLock);
249 android::base::ScopedLockAssertion assumeLocked(mLock);
250 AnrResult result;
251 ASSERT_NO_FATAL_FAILURE(result =
252 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000253 ASSERT_EQ(expectedToken, result.token);
254 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500255 }
256
Prabir Pradhanedd96402022-02-15 01:46:16 -0800257 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000258 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500259 std::unique_lock lock(mLock);
260 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800261 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
262 const auto& [token, _] = result;
263 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000264 }
265
Prabir Pradhanedd96402022-02-15 01:46:16 -0800266 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000267 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800268 std::unique_lock lock(mLock);
269 android::base::ScopedLockAssertion assumeLocked(mLock);
270 AnrResult result;
271 ASSERT_NO_FATAL_FAILURE(
272 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000273 ASSERT_EQ(expectedToken, result.token);
274 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800275 }
276
277 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000278 sp<IBinder> getResponsiveWindowToken() {
279 std::unique_lock lock(mLock);
280 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
282 const auto& [token, _] = result;
283 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700284 }
285
286 void assertNotifyAnrWasNotCalled() {
287 std::scoped_lock lock(mLock);
288 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800289 ASSERT_TRUE(mAnrWindows.empty());
290 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500291 << "ANR was not called, but please also consume the 'connection is responsive' "
292 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700293 }
294
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000295 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800296 std::unique_lock lock(mLock);
297 base::ScopedLockAssertion assumeLocked(mLock);
298
299 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
300 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000301 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800302 enabled;
303 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000304 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
305 << ") to be called.";
306 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800307 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000308 auto request = *mPointerCaptureRequest;
309 mPointerCaptureRequest.reset();
310 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800311 }
312
313 void assertSetPointerCaptureNotCalled() {
314 std::unique_lock lock(mLock);
315 base::ScopedLockAssertion assumeLocked(mLock);
316
317 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000318 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800319 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800321 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000322 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800323 }
324
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700325 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
326 const sp<IBinder>& targetToken) {
327 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800328 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800329 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800330 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800331 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800332 }
333
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800334 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
335 std::unique_lock lock(mLock);
336 base::ScopedLockAssertion assumeLocked(mLock);
337 std::optional<sp<IBinder>> receivedToken =
338 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
339 mNotifyInputChannelBroken);
340 ASSERT_TRUE(receivedToken.has_value());
341 ASSERT_EQ(token, *receivedToken);
342 }
343
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800344 /**
345 * Set policy timeout. A value of zero means next key will not be intercepted.
346 */
347 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
348 mInterceptKeyTimeout = timeout;
349 }
350
Josep del Riob3981622023-04-18 15:49:45 +0000351 void assertUserActivityPoked() {
352 std::scoped_lock lock(mLock);
353 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
354 }
355
356 void assertUserActivityNotPoked() {
357 std::scoped_lock lock(mLock);
358 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
359 }
360
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000361 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000362 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
363 }
364
365 void assertNotifyDeviceInteractionWasNotCalled() {
366 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
367 }
368
Michael Wrightd02c5b62014-02-10 15:10:22 -0800369private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700370 std::mutex mLock;
371 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
372 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
373 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
374 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800375
Prabir Pradhan99987712020-11-10 18:43:05 -0800376 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000377
378 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800379
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700380 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700381 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800382 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
383 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700384 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800385 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
386 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700387
arthurhungf452d0b2021-01-06 00:19:52 +0800388 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800389 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000390 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800391
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800392 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
393
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000394 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000395
Prabir Pradhanedd96402022-02-15 01:46:16 -0800396 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
397 // for a specific container to become non-empty. When the container is non-empty, return the
398 // first entry from the container and erase it.
399 template <class T>
400 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
401 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
402 // If there is an ANR, Dispatcher won't be idle because there are still events
403 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
404 // before checking if ANR was called.
405 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
406 // to provide it some time to act. 100ms seems reasonable.
407 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
408 const std::chrono::time_point start = std::chrono::steady_clock::now();
409 std::optional<T> token =
410 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
411 if (!token.has_value()) {
412 ADD_FAILURE() << "Did not receive the ANR callback";
413 return {};
414 }
415
416 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
417 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
418 // the dispatcher started counting before this function was called
419 if (std::chrono::abs(timeout - waited) > 100ms) {
420 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
421 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
422 << "ms, but waited "
423 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
424 << "ms instead";
425 }
426 return *token;
427 }
428
429 template <class T>
430 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
431 std::queue<T>& storage,
432 std::unique_lock<std::mutex>& lock,
433 std::condition_variable& condition)
434 REQUIRES(mLock) {
435 condition.wait_for(lock, timeout,
436 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
437 if (storage.empty()) {
438 ADD_FAILURE() << "Did not receive the expected callback";
439 return std::nullopt;
440 }
441 T item = storage.front();
442 storage.pop();
443 return std::make_optional(item);
444 }
445
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600446 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700447 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800448 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800449 }
450
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000451 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800452 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700453 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800454 ASSERT_TRUE(pid.has_value());
455 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700456 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500457 }
458
Prabir Pradhanedd96402022-02-15 01:46:16 -0800459 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000460 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500461 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800462 ASSERT_TRUE(pid.has_value());
463 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500464 mNotifyAnr.notify_all();
465 }
466
467 void notifyNoFocusedWindowAnr(
468 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
469 std::scoped_lock lock(mLock);
470 mAnrApplications.push(applicationHandle);
471 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800472 }
473
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800474 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
475 std::scoped_lock lock(mLock);
476 mBrokenInputChannels.push(connectionToken);
477 mNotifyInputChannelBroken.notify_all();
478 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800479
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600480 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700481
Chris Yef59a2f42020-10-16 12:55:26 -0700482 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
483 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
484 const std::vector<float>& values) override {}
485
486 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
487 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000488
Chris Yefb552902021-02-03 17:18:37 -0800489 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
490
Prabir Pradhana41d2442023-04-20 21:30:40 +0000491 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700492 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000493 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700494 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000495 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
496 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800497 break;
498 }
499
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700500 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000501 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
502 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800503 break;
504 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700505 default: {
506 ADD_FAILURE() << "Should only filter keys or motions";
507 break;
508 }
Jackal Guof9696682018-10-05 12:23:23 +0800509 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800510 return true;
511 }
512
Prabir Pradhana41d2442023-04-20 21:30:40 +0000513 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
514 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800515 // Clear intercept state when we handled the event.
516 mInterceptKeyTimeout = 0ms;
517 }
518 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800519
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600520 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521
Prabir Pradhana41d2442023-04-20 21:30:40 +0000522 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800523 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
524 // Clear intercept state so we could dispatch the event in next wake.
525 mInterceptKeyTimeout = 0ms;
526 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800527 }
528
Prabir Pradhana41d2442023-04-20 21:30:40 +0000529 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
530 uint32_t) override {
531 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800532 }
533
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600534 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
535 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700536 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800537 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
538 * essentially a passthrough for notifySwitch.
539 */
Harry Cutts33476232023-01-30 19:57:29 +0000540 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541 }
542
Josep del Riob3981622023-04-18 15:49:45 +0000543 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
544 std::scoped_lock lock(mLock);
545 mPokedUserActivity = true;
546 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800547
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600548 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700549 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700550 mOnPointerDownToken = newToken;
551 }
552
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000553 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800554 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000555 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800556 mPointerCaptureChangedCondition.notify_all();
557 }
558
arthurhungf452d0b2021-01-06 00:19:52 +0800559 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
560 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800561 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800562 mDropTargetWindowToken = token;
563 }
564
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000565 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000566 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000567 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
568 }
569
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700570 void assertFilterInputEventWasCalledInternal(
571 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700572 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800573 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700574 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800575 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800576 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700578} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580// --- InputDispatcherTest ---
581
582class InputDispatcherTest : public testing::Test {
583protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700585 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000587 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000588 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
589 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000590 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000591 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700592 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000595 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700596 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000597 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700598 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700600
601 /**
602 * Used for debugging when writing the test
603 */
604 void dumpDispatcherState() {
605 std::string dump;
606 mDispatcher->dump(dump);
607 std::stringstream ss(dump);
608 std::string to;
609
610 while (std::getline(ss, to, '\n')) {
611 ALOGE("%s", to.c_str());
612 }
613 }
Vishnu Nair958da932020-08-21 17:12:37 -0700614
Chavi Weingarten847e8512023-03-29 00:26:09 +0000615 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700616 FocusRequest request;
617 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000618 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700619 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
620 request.displayId = window->getInfo()->displayId;
621 mDispatcher->setFocusedWindow(request);
622 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623};
624
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
626 KeyEvent event;
627
628 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800629 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
630 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600632 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800633 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000634 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000635 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800636 << "Should reject key events with undefined action.";
637
638 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800639 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
640 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600641 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800642 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000643 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000644 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800645 << "Should reject key events with ACTION_MULTIPLE.";
646}
647
648TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
649 MotionEvent event;
650 PointerProperties pointerProperties[MAX_POINTERS + 1];
651 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800652 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 pointerProperties[i].clear();
654 pointerProperties[i].id = i;
655 pointerCoords[i].clear();
656 }
657
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800658 // Some constants commonly used below
659 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
660 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
661 constexpr int32_t metaState = AMETA_NONE;
662 constexpr MotionClassification classification = MotionClassification::NONE;
663
chaviw9eaa22c2020-07-01 16:21:27 -0700664 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800666 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000667 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700668 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700669 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
670 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000671 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800672 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000673 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000674 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800675 << "Should reject motion events with undefined action.";
676
677 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800678 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800679 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
680 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
681 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
682 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000683 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800684 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000685 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000686 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800687 << "Should reject motion events with pointer down index too large.";
688
Garfield Tanfbe732e2020-01-24 11:26:14 -0800689 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700690 AMOTION_EVENT_ACTION_POINTER_DOWN |
691 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700692 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
693 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700694 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000695 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000697 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 << "Should reject motion events with pointer down index too small.";
700
701 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800702 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800703 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
704 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
705 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
706 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000707 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800708 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000709 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000710 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800711 << "Should reject motion events with pointer up index too large.";
712
Garfield Tanfbe732e2020-01-24 11:26:14 -0800713 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700714 AMOTION_EVENT_ACTION_POINTER_UP |
715 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700716 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
717 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700718 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000719 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800720 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000721 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000722 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800723 << "Should reject motion events with pointer up index too small.";
724
725 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800726 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
727 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700728 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700729 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
730 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000731 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000733 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject motion events with 0 pointers.";
736
Garfield Tanfbe732e2020-01-24 11:26:14 -0800737 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
738 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700739 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700740 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
741 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000742 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800743 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000744 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000745 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800746 << "Should reject motion events with more than MAX_POINTERS pointers.";
747
748 // Rejects motion events with invalid pointer ids.
749 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800750 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
751 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700752 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700753 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
754 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000755 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800756 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000757 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000758 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800759 << "Should reject motion events with pointer ids less than 0.";
760
761 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800762 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
763 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700764 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700765 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
766 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000767 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800768 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000769 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000770 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800771 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
772
773 // Rejects motion events with duplicate pointer ids.
774 pointerProperties[0].id = 1;
775 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800776 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
777 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700778 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700779 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
780 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000781 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000783 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000784 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800785 << "Should reject motion events with duplicate pointer ids.";
786}
787
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800788/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
789
790TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
791 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000792 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800793 ASSERT_TRUE(mDispatcher->waitForIdle());
794
795 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
796}
797
798TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000799 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
800 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000801 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800802
803 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
804 args.policyFlags |= POLICY_FLAG_TRUSTED;
805 mFakePolicy->assertNotifySwitchWasCalled(args);
806}
807
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700808namespace {
809
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700810static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700811// Default input dispatching timeout if there is no focused application or paused window
812// from which to determine an appropriate dispatching timeout.
813static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
814 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
815 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800816
817class FakeApplicationHandle : public InputApplicationHandle {
818public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700819 FakeApplicationHandle() {
820 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700821 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500822 mInfo.dispatchingTimeoutMillis =
823 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700824 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800825 virtual ~FakeApplicationHandle() {}
826
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000827 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700828
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500829 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
830 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700831 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800832};
833
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800834class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800835public:
Garfield Tan15601662020-09-22 15:32:38 -0700836 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800837 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700838 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800839 }
840
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700841 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700842 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700843 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700844 if (!consumeSeq) {
845 return nullptr;
846 }
847 finishEvent(*consumeSeq);
848 return event;
849 }
850
851 /**
852 * Receive an event without acknowledging it.
853 * Return the sequence number that could later be used to send finished signal.
854 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700855 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
856 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800857 uint32_t consumeSeq;
858 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800859
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800860 std::chrono::time_point start = std::chrono::steady_clock::now();
861 status_t status = WOULD_BLOCK;
862 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000863 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800864 &event);
865 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700866 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800867 break;
868 }
869 }
870
871 if (status == WOULD_BLOCK) {
872 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800874 }
875
876 if (status != OK) {
877 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700878 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800879 }
880 if (event == nullptr) {
881 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 if (outEvent != nullptr) {
885 *outEvent = event;
886 }
887 return consumeSeq;
888 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800889
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700890 /**
891 * To be used together with "receiveEvent" to complete the consumption of an event.
892 */
893 void finishEvent(uint32_t consumeSeq) {
894 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
895 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896 }
897
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000898 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
899 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
900 ASSERT_EQ(OK, status);
901 }
902
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700903 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000904 std::optional<int32_t> expectedDisplayId,
905 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700906 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800907
908 ASSERT_NE(nullptr, event) << mName.c_str()
909 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800910 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700911 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
912 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800913
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000914 if (expectedDisplayId.has_value()) {
915 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
916 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800917
Tiger Huang8664f8c2018-10-11 19:14:35 +0800918 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700919 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800920 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700921 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000922 if (expectedFlags.has_value()) {
923 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
924 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800925 break;
926 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700927 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800928 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700929 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000930 if (expectedFlags.has_value()) {
931 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
932 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800933 break;
934 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700935 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100936 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
937 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700938 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800939 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
940 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700941 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000942 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
943 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700944 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800945 FAIL() << "Use 'consumeDragEvent' for DRAG events";
946 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800947 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800948 }
949
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800950 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700951 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800952
953 if (event == nullptr) {
954 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
955 return nullptr;
956 }
957
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 if (event->getType() != InputEventType::MOTION) {
959 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800960 return nullptr;
961 }
962 return static_cast<MotionEvent*>(event);
963 }
964
965 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
966 MotionEvent* motionEvent = consumeMotion();
967 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
968 ASSERT_THAT(*motionEvent, matcher);
969 }
970
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100971 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700972 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100973 ASSERT_NE(nullptr, event) << mName.c_str()
974 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700975 ASSERT_EQ(InputEventType::FOCUS, event->getType())
976 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100977
978 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
979 << mName.c_str() << ": event displayId should always be NONE.";
980
981 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
982 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100983 }
984
Prabir Pradhan99987712020-11-10 18:43:05 -0800985 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700986 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -0800987 ASSERT_NE(nullptr, event) << mName.c_str()
988 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
990 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -0800991
992 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
993 << mName.c_str() << ": event displayId should always be NONE.";
994
995 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
996 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
997 }
998
arthurhungb89ccb02020-12-30 16:19:01 +0800999 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001000 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001001 ASSERT_NE(nullptr, event) << mName.c_str()
1002 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001003 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001004
1005 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1006 << mName.c_str() << ": event displayId should always be NONE.";
1007
1008 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1009 EXPECT_EQ(isExiting, dragEvent.isExiting());
1010 EXPECT_EQ(x, dragEvent.getX());
1011 EXPECT_EQ(y, dragEvent.getY());
1012 }
1013
Antonio Kantekf16f2832021-09-28 04:39:20 +00001014 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001015 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001016 ASSERT_NE(nullptr, event) << mName.c_str()
1017 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001018 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1019 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001020
1021 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1022 << mName.c_str() << ": event displayId should always be NONE.";
1023 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1024 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1025 }
1026
chaviwd1c23182019-12-20 18:44:56 -08001027 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001028 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001029 if (event == nullptr) {
1030 return;
1031 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001032 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001033 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1034 ADD_FAILURE() << "Received key event "
1035 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001036 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001037 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1038 ADD_FAILURE() << "Received motion event "
1039 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001040 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001041 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1042 ADD_FAILURE() << "Received focus event, hasFocus = "
1043 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001044 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001045 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1046 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1047 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001048 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001049 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1050 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1051 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 }
1053 FAIL() << mName.c_str()
1054 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001055 }
1056
1057 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1058
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001059 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1060
chaviwd1c23182019-12-20 18:44:56 -08001061protected:
1062 std::unique_ptr<InputConsumer> mConsumer;
1063 PreallocatedInputEventFactory mEventFactory;
1064
1065 std::string mName;
1066};
1067
chaviw3277faf2021-05-19 16:45:23 -05001068class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001069public:
1070 static const int32_t WIDTH = 600;
1071 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001072
Chris Yea209fde2020-07-22 13:54:51 -07001073 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001074 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001075 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001076 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001077 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001078 base::Result<std::unique_ptr<InputChannel>> channel =
1079 dispatcher->createInputChannel(name);
1080 token = (*channel)->getConnectionToken();
1081 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001082 }
1083
1084 inputApplicationHandle->updateInfo();
1085 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1086
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001087 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001088 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001089 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001090 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001091 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001092 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001093 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001094 mInfo.globalScaleFactor = 1.0;
1095 mInfo.touchableRegion.clear();
1096 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001097 mInfo.ownerPid = WINDOW_PID;
1098 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001099 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001100 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001101 }
1102
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001103 sp<FakeWindowHandle> clone(int32_t displayId) {
1104 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1105 handle->mInfo = mInfo;
1106 handle->mInfo.displayId = displayId;
1107 handle->mInfo.id = sId++;
1108 handle->mInputReceiver = mInputReceiver;
1109 return handle;
1110 }
1111
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001112 void setTouchable(bool touchable) {
1113 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1114 }
chaviwd1c23182019-12-20 18:44:56 -08001115
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001116 void setFocusable(bool focusable) {
1117 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1118 }
1119
1120 void setVisible(bool visible) {
1121 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1122 }
Vishnu Nair958da932020-08-21 17:12:37 -07001123
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001124 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001125 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001126 }
1127
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001128 void setPaused(bool paused) {
1129 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1130 }
1131
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001132 void setPreventSplitting(bool preventSplitting) {
1133 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001134 }
1135
1136 void setSlippery(bool slippery) {
1137 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1138 }
1139
1140 void setWatchOutsideTouch(bool watchOutside) {
1141 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1142 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001143
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001144 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1145
1146 void setInterceptsStylus(bool interceptsStylus) {
1147 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1148 }
1149
1150 void setDropInput(bool dropInput) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1152 }
1153
1154 void setDropInputIfObscured(bool dropInputIfObscured) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1156 }
1157
1158 void setNoInputChannel(bool noInputChannel) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1160 }
1161
Josep del Riob3981622023-04-18 15:49:45 +00001162 void setDisableUserActivity(bool disableUserActivity) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1164 }
1165
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001166 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1167
chaviw3277faf2021-05-19 16:45:23 -05001168 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001169
Bernardo Rufino7393d172021-02-26 13:56:11 +00001170 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1171
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001172 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001173 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001174 mInfo.touchableRegion.clear();
1175 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001176
1177 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1178 ui::Transform translate;
1179 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1180 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001181 }
1182
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001183 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1184
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001185 void setIsWallpaper(bool isWallpaper) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1187 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001188
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001189 void setDupTouchToWallpaper(bool hasWallpaper) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1191 }
chaviwd1c23182019-12-20 18:44:56 -08001192
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001193 void setTrustedOverlay(bool trustedOverlay) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1195 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001196
chaviw9eaa22c2020-07-01 16:21:27 -07001197 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1198 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1199 }
1200
1201 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001202
yunho.shinf4a80b82020-11-16 21:13:57 +09001203 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1204
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001205 KeyEvent* consumeKey() {
1206 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1207 if (event == nullptr) {
1208 ADD_FAILURE() << "Consume failed : no event";
1209 return nullptr;
1210 }
1211 if (event->getType() != InputEventType::KEY) {
1212 ADD_FAILURE() << "Instead of key event, got " << *event;
1213 return nullptr;
1214 }
1215 return static_cast<KeyEvent*>(event);
1216 }
1217
1218 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1219 KeyEvent* keyEvent = consumeKey();
1220 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1221 ASSERT_THAT(*keyEvent, matcher);
1222 }
1223
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001224 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001225 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001226 }
1227
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001228 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001229 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001230 }
1231
Svet Ganov5d3bc372020-01-26 23:11:07 -08001232 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001233 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001234 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1235 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001236 }
1237
1238 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001239 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001240 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1241 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001242 }
1243
1244 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001245 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001246 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1247 }
1248
1249 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1250 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001251 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001252 expectedFlags);
1253 }
1254
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001256 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1257 int32_t expectedFlags = 0) {
1258 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1259 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001260 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 }
1262
1263 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedFlags = 0) {
1265 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1266 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001267 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001268 }
1269
1270 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001271 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001272 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001273 expectedFlags);
1274 }
1275
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001276 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1277 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001278 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001279 expectedFlags);
1280 }
1281
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001282 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1283 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001284 MotionEvent* motionEvent = consumeMotion();
1285 ASSERT_NE(nullptr, motionEvent);
1286 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1287 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1288 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001289 }
1290
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001291 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1292 ASSERT_NE(mInputReceiver, nullptr)
1293 << "Cannot consume events from a window with no receiver";
1294 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1295 }
1296
Prabir Pradhan99987712020-11-10 18:43:05 -08001297 void consumeCaptureEvent(bool hasCapture) {
1298 ASSERT_NE(mInputReceiver, nullptr)
1299 << "Cannot consume events from a window with no receiver";
1300 mInputReceiver->consumeCaptureEvent(hasCapture);
1301 }
1302
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001303 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1304 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001305 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001306 ASSERT_THAT(*motionEvent, matcher);
1307 }
1308
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001309 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001310 std::optional<int32_t> expectedDisplayId,
1311 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001312 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1313 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1314 expectedFlags);
1315 }
1316
arthurhungb89ccb02020-12-30 16:19:01 +08001317 void consumeDragEvent(bool isExiting, float x, float y) {
1318 mInputReceiver->consumeDragEvent(isExiting, x, y);
1319 }
1320
Antonio Kantekf16f2832021-09-28 04:39:20 +00001321 void consumeTouchModeEvent(bool inTouchMode) {
1322 ASSERT_NE(mInputReceiver, nullptr)
1323 << "Cannot consume events from a window with no receiver";
1324 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1325 }
1326
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001327 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001328 if (mInputReceiver == nullptr) {
1329 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1330 return std::nullopt;
1331 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001332 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001333 }
1334
1335 void finishEvent(uint32_t sequenceNum) {
1336 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1337 mInputReceiver->finishEvent(sequenceNum);
1338 }
1339
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001340 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1341 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1342 mInputReceiver->sendTimeline(inputEventId, timeline);
1343 }
1344
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001345 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001346 if (mInputReceiver == nullptr) {
1347 return nullptr;
1348 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001349 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001350 }
1351
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001352 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001353 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001354 if (event == nullptr) {
1355 ADD_FAILURE() << "Consume failed : no event";
1356 return nullptr;
1357 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001358 if (event->getType() != InputEventType::MOTION) {
1359 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001360 return nullptr;
1361 }
1362 return static_cast<MotionEvent*>(event);
1363 }
1364
Arthur Hungb92218b2018-08-14 12:00:21 +08001365 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001366 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001367 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001368 return; // Can't receive events if the window does not have input channel
1369 }
1370 ASSERT_NE(nullptr, mInputReceiver)
1371 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001372 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001373 }
1374
chaviwaf87b3e2019-10-01 16:59:28 -07001375 sp<IBinder> getToken() { return mInfo.token; }
1376
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001377 const std::string& getName() { return mName; }
1378
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001379 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001380 mInfo.ownerPid = ownerPid;
1381 mInfo.ownerUid = ownerUid;
1382 }
1383
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001384 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001385
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001386 void destroyReceiver() { mInputReceiver = nullptr; }
1387
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001388 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1389
chaviwd1c23182019-12-20 18:44:56 -08001390private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001391 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001392 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001393 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001394 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001395 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001396};
1397
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001398std::atomic<int32_t> FakeWindowHandle::sId{1};
1399
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001400class FakeMonitorReceiver {
1401public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001402 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001403 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001404 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001405 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1406 }
1407
1408 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1409
1410 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1411 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1412 expectedFlags);
1413 }
1414
1415 std::optional<int32_t> receiveEvent() {
1416 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1417 }
1418
1419 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1420
1421 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1422 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1423 expectedDisplayId, expectedFlags);
1424 }
1425
1426 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1427 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1428 expectedDisplayId, expectedFlags);
1429 }
1430
1431 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1432 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1433 expectedDisplayId, expectedFlags);
1434 }
1435
1436 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1437 mInputReceiver->consumeMotionEvent(
1438 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1439 WithDisplayId(expectedDisplayId),
1440 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1441 }
1442
1443 void consumeMotionPointerDown(int32_t pointerIdx) {
1444 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1445 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1446 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1447 /*expectedFlags=*/0);
1448 }
1449
1450 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1451 mInputReceiver->consumeMotionEvent(matcher);
1452 }
1453
1454 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1455
1456 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1457
1458private:
1459 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1460};
1461
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001462static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001463 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001464 int32_t displayId = ADISPLAY_ID_NONE,
1465 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001466 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001467 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001468 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001469 KeyEvent event;
1470 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1471
1472 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001473 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001474 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1475 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001476
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001477 if (!allowKeyRepeat) {
1478 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1479 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001480 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001481 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001482}
1483
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001484static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1485 InputEventInjectionResult result =
1486 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1487 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1488 if (result != InputEventInjectionResult::TIMED_OUT) {
1489 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1490 }
1491}
1492
1493static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001494 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001495 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001496}
1497
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001498// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1499// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1500// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001501static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1502 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001503 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001504 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001505 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001506}
1507
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001508static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001509 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001510 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001511}
1512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001513static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001514 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001515 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001516 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001517 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1519 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001520}
1521
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001522static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001523 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1524 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001525 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001526 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1527 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001528 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001529 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001530 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001531 MotionEventBuilder motionBuilder =
1532 MotionEventBuilder(action, source)
1533 .displayId(displayId)
1534 .eventTime(eventTime)
1535 .rawXCursorPosition(cursorPosition.x)
1536 .rawYCursorPosition(cursorPosition.y)
1537 .pointer(
1538 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1539 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1540 motionBuilder.downTime(eventTime);
1541 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001542
1543 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001544 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1545 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001546}
1547
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001548static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1549 int32_t displayId,
1550 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001551 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001552}
1553
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001554static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1555 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001556 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001557 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001558}
1559
Jackal Guof9696682018-10-05 12:23:23 +08001560static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1561 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1562 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001563 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001564 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1565 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001566
1567 return args;
1568}
1569
Josep del Riob3981622023-04-18 15:49:45 +00001570static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1571 int32_t displayId = ADISPLAY_ID_NONE) {
1572 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1573 // Define a valid key event.
1574 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001575 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001576 currentTime);
1577
1578 return args;
1579}
1580
1581static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1582 int32_t displayId = ADISPLAY_ID_NONE) {
1583 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1584 // Define a valid key event.
1585 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001586 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001587 AMETA_NONE, currentTime);
1588
1589 return args;
1590}
1591
Prabir Pradhan678438e2023-04-13 19:32:51 +00001592[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1593 int32_t displayId,
1594 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001595 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001596 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1597 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1598 }
1599
chaviwd1c23182019-12-20 18:44:56 -08001600 PointerProperties pointerProperties[pointerCount];
1601 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001602
chaviwd1c23182019-12-20 18:44:56 -08001603 for (size_t i = 0; i < pointerCount; i++) {
1604 pointerProperties[i].clear();
1605 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001606 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001607
chaviwd1c23182019-12-20 18:44:56 -08001608 pointerCoords[i].clear();
1609 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1610 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1611 }
Jackal Guof9696682018-10-05 12:23:23 +08001612
1613 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1614 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001615 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001616 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1617 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001618 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001619 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001620 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001621 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001622
1623 return args;
1624}
1625
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001626static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1627 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1628}
1629
chaviwd1c23182019-12-20 18:44:56 -08001630static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1631 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1632}
1633
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001634static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1635 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001636 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001637}
1638
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001639} // namespace
1640
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001641/**
1642 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1643 * broken channel.
1644 */
1645TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1647 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001648 sp<FakeWindowHandle>::make(application, mDispatcher,
1649 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001650
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001651 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001652
1653 // Window closes its channel, but the window remains.
1654 window->destroyReceiver();
1655 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1656}
1657
Arthur Hungb92218b2018-08-14 12:00:21 +08001658TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1661 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001662
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001663 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001667
1668 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001669 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001670}
1671
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001672TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1675 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001676
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001678 // Inject a MotionEvent to an unknown display.
1679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001680 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1682
1683 // Window should receive motion event.
1684 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1685}
1686
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001688 * Calling onWindowInfosChanged once should not cause any issues.
1689 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 * called twice.
1691 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001692TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001694 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1695 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001698 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703
1704 // Window should receive motion event.
1705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1706}
1707
1708/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710 */
1711TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1714 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723
1724 // Window should receive motion event.
1725 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1726}
1727
Arthur Hungb92218b2018-08-14 12:00:21 +08001728// The foreground window should receive the first touch down event.
1729TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001731 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001733 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001734 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001735
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001736 mDispatcher->onWindowInfosChanged(
1737 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001741
1742 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001743 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001744 windowSecond->assertNoEvents();
1745}
1746
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001747/**
1748 * Two windows: A top window, and a wallpaper behind the window.
1749 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1750 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001751 * 1. foregroundWindow <-- dup touch to wallpaper
1752 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001753 */
1754TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1756 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001757 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001758 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001759 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001760 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001761 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001762
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001763 mDispatcher->onWindowInfosChanged(
1764 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001767 {100, 200}))
1768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1769
1770 // Both foreground window and its wallpaper should receive the touch down
1771 foregroundWindow->consumeMotionDown();
1772 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1773
1774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001775 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776 ADISPLAY_ID_DEFAULT, {110, 200}))
1777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1778
1779 foregroundWindow->consumeMotionMove();
1780 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1781
1782 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001783 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784 foregroundWindow->consumeMotionCancel();
1785 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1786 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1787}
1788
1789/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001790 * Two fingers down on the window, and lift off the first finger.
1791 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1792 * contains a single pointer.
1793 */
1794TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1796 sp<FakeWindowHandle> window =
1797 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1798
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1802 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1803 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001804 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001805 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1806 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1807 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1808 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001809 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001810 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1811 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1812 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1813 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001814 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1815 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1816 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1817
1818 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001819 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001820 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1821 window->consumeMotionEvent(
1822 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1823}
1824
1825/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1827 * with the following differences:
1828 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1829 * clean up the connection.
1830 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1831 * Ensure that there's no crash in the dispatcher.
1832 */
1833TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1835 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001836 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001837 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001838 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001839 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001840 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001841
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged(
1843 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001845 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001846 {100, 200}))
1847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1848
1849 // Both foreground window and its wallpaper should receive the touch down
1850 foregroundWindow->consumeMotionDown();
1851 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1852
1853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001854 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001855 ADISPLAY_ID_DEFAULT, {110, 200}))
1856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1857
1858 foregroundWindow->consumeMotionMove();
1859 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1860
1861 // Wallpaper closes its channel, but the window remains.
1862 wallpaperWindow->destroyReceiver();
1863 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1864
1865 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1866 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001867 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001868 foregroundWindow->consumeMotionCancel();
1869}
1870
Arthur Hungc539dbb2022-12-08 07:45:36 +00001871class ShouldSplitTouchFixture : public InputDispatcherTest,
1872 public ::testing::WithParamInterface<bool> {};
1873INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1874 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001875/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876 * A single window that receives touch (on top), and a wallpaper window underneath it.
1877 * The top window gets a multitouch gesture.
1878 * Ensure that wallpaper gets the same gesture.
1879 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001880TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001882 sp<FakeWindowHandle> foregroundWindow =
1883 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1884 foregroundWindow->setDupTouchToWallpaper(true);
1885 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001886
1887 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001888 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001889 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001891 mDispatcher->onWindowInfosChanged(
1892 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893
1894 // Touch down on top window
1895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001896 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897 {100, 100}))
1898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1899
1900 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001901 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1903
1904 // Second finger down on the top window
1905 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001906 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001908 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1909 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001910 .build();
1911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001912 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913 InputEventInjectionSync::WAIT_FOR_RESULT))
1914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1915
Harry Cutts33476232023-01-30 19:57:29 +00001916 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1917 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001919
1920 const MotionEvent secondFingerUpEvent =
1921 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1922 .displayId(ADISPLAY_ID_DEFAULT)
1923 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001924 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1925 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001926 .build();
1927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001928 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001929 InputEventInjectionSync::WAIT_FOR_RESULT))
1930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1931 foregroundWindow->consumeMotionPointerUp(0);
1932 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1933
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001936 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1937 AINPUT_SOURCE_TOUCHSCREEN)
1938 .displayId(ADISPLAY_ID_DEFAULT)
1939 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001941 .x(100)
1942 .y(100))
1943 .build(),
1944 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1946 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1947 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948}
1949
1950/**
1951 * Two windows: a window on the left and window on the right.
1952 * A third window, wallpaper, is behind both windows, and spans both top windows.
1953 * The first touch down goes to the left window. A second pointer touches down on the right window.
1954 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1955 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1956 * ACTION_POINTER_DOWN(1).
1957 */
1958TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1960 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001961 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001963 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964
1965 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001966 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001967 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001968 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969
1970 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001971 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001973 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001975 mDispatcher->onWindowInfosChanged(
1976 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1977 {},
1978 0,
1979 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980
1981 // Touch down on left window
1982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001983 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984 {100, 100}))
1985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1986
1987 // Both foreground window and its wallpaper should receive the touch down
1988 leftWindow->consumeMotionDown();
1989 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1990
1991 // Second finger down on the right window
1992 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001993 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001994 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001995 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1996 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997 .build();
1998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001999 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000 InputEventInjectionSync::WAIT_FOR_RESULT))
2001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2002
2003 leftWindow->consumeMotionMove();
2004 // Since the touch is split, right window gets ACTION_DOWN
2005 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002006 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007 expectedWallpaperFlags);
2008
2009 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002010 mDispatcher->onWindowInfosChanged(
2011 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 leftWindow->consumeMotionCancel();
2013 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2014 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2015
2016 // The pointer that's still down on the right window moves, and goes to the right window only.
2017 // As far as the dispatcher's concerned though, both pointers are still present.
2018 const MotionEvent secondFingerMoveEvent =
2019 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2020 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002021 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2022 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 .build();
2024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002025 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026 InputEventInjectionSync::WAIT_FOR_RESULT));
2027 rightWindow->consumeMotionMove();
2028
2029 leftWindow->assertNoEvents();
2030 rightWindow->assertNoEvents();
2031 wallpaperWindow->assertNoEvents();
2032}
2033
Arthur Hungc539dbb2022-12-08 07:45:36 +00002034/**
2035 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2036 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2037 * The right window should receive ACTION_DOWN.
2038 */
2039TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041 sp<FakeWindowHandle> leftWindow =
2042 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2043 leftWindow->setFrame(Rect(0, 0, 200, 200));
2044 leftWindow->setDupTouchToWallpaper(true);
2045 leftWindow->setSlippery(true);
2046
2047 sp<FakeWindowHandle> rightWindow =
2048 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2049 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002050
2051 sp<FakeWindowHandle> wallpaperWindow =
2052 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2053 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002054
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002055 mDispatcher->onWindowInfosChanged(
2056 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2057 {},
2058 0,
2059 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002060
Arthur Hungc539dbb2022-12-08 07:45:36 +00002061 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002063 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002064 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002066
2067 // Both foreground window and its wallpaper should receive the touch down
2068 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002069 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2070
Arthur Hungc539dbb2022-12-08 07:45:36 +00002071 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002073 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002074 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002075 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2076
Arthur Hungc539dbb2022-12-08 07:45:36 +00002077 leftWindow->consumeMotionCancel();
2078 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2079 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002080}
2081
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002082/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002083 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2084 * interactive, it might stop sending this flag.
2085 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2086 * to have a consistent input stream.
2087 *
2088 * Test procedure:
2089 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2090 * DOWN (new gesture).
2091 *
2092 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2093 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2094 *
2095 * We technically just need a single window here, but we are using two windows (spy on top and a
2096 * regular window below) to emulate the actual situation where it happens on the device.
2097 */
2098TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2100 sp<FakeWindowHandle> spyWindow =
2101 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2102 spyWindow->setFrame(Rect(0, 0, 200, 200));
2103 spyWindow->setTrustedOverlay(true);
2104 spyWindow->setSpy(true);
2105
2106 sp<FakeWindowHandle> window =
2107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2108 window->setFrame(Rect(0, 0, 200, 200));
2109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002110 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002111 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002112
2113 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002114 mDispatcher->notifyMotion(
2115 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2116 .deviceId(touchDeviceId)
2117 .policyFlags(DEFAULT_POLICY_FLAGS)
2118 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2119 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002120
Prabir Pradhan678438e2023-04-13 19:32:51 +00002121 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2122 .deviceId(touchDeviceId)
2123 .policyFlags(DEFAULT_POLICY_FLAGS)
2124 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2125 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2126 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2128 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2129 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2130 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2131
2132 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002133 mDispatcher->notifyMotion(
2134 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2135 .deviceId(touchDeviceId)
2136 .policyFlags(0)
2137 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2138 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2139 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002140 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2141 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2142
2143 // We don't need to reset the device to reproduce the issue, but the reset event typically
2144 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002145 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002146
2147 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002148 mDispatcher->notifyMotion(
2149 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2150 .deviceId(touchDeviceId)
2151 .policyFlags(DEFAULT_POLICY_FLAGS)
2152 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2153 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002154 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2155 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2156
2157 // No more events
2158 spyWindow->assertNoEvents();
2159 window->assertNoEvents();
2160}
2161
2162/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002163 * Two windows: a window on the left and a window on the right.
2164 * Mouse is hovered from the right window into the left window.
2165 * Next, we tap on the left window, where the cursor was last seen.
2166 * The second tap is done onto the right window.
2167 * The mouse and tap are from two different devices.
2168 * We technically don't need to set the downtime / eventtime for these events, but setting these
2169 * explicitly helps during debugging.
2170 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2171 * In the buggy implementation, a tap on the right window would cause a crash.
2172 */
2173TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2175 sp<FakeWindowHandle> leftWindow =
2176 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2177 leftWindow->setFrame(Rect(0, 0, 200, 200));
2178
2179 sp<FakeWindowHandle> rightWindow =
2180 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2181 rightWindow->setFrame(Rect(200, 0, 400, 200));
2182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002183 mDispatcher->onWindowInfosChanged(
2184 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2186 // stale.
2187 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2188 const int32_t mouseDeviceId = 6;
2189 const int32_t touchDeviceId = 4;
2190 // Move the cursor from right
2191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002192 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002193 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2194 AINPUT_SOURCE_MOUSE)
2195 .deviceId(mouseDeviceId)
2196 .downTime(baseTime + 10)
2197 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002198 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002199 .build()));
2200 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2201
2202 // .. to the left window
2203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002204 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002205 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2206 AINPUT_SOURCE_MOUSE)
2207 .deviceId(mouseDeviceId)
2208 .downTime(baseTime + 10)
2209 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002210 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002211 .build()));
2212 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2213 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2214 // Now tap the left window
2215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002216 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002217 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2218 AINPUT_SOURCE_TOUCHSCREEN)
2219 .deviceId(touchDeviceId)
2220 .downTime(baseTime + 40)
2221 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002222 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002223 .build()));
2224 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2225 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2226
2227 // release tap
2228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002229 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002230 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2231 AINPUT_SOURCE_TOUCHSCREEN)
2232 .deviceId(touchDeviceId)
2233 .downTime(baseTime + 40)
2234 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002235 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002236 .build()));
2237 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2238
2239 // Tap the window on the right
2240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002241 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002242 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2243 AINPUT_SOURCE_TOUCHSCREEN)
2244 .deviceId(touchDeviceId)
2245 .downTime(baseTime + 60)
2246 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002247 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 .build()));
2249 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2250
2251 // release tap
2252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002254 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2255 AINPUT_SOURCE_TOUCHSCREEN)
2256 .deviceId(touchDeviceId)
2257 .downTime(baseTime + 60)
2258 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002259 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002260 .build()));
2261 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2262
2263 // No more events
2264 leftWindow->assertNoEvents();
2265 rightWindow->assertNoEvents();
2266}
2267
2268/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002269 * Start hovering in a window. While this hover is still active, make another window appear on top.
2270 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2271 * While the top window is present, the hovering is stopped.
2272 * Later, hovering gets resumed again.
2273 * Ensure that new hover gesture is handled correctly.
2274 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2275 * to the window that's currently being hovered over.
2276 */
2277TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2279 sp<FakeWindowHandle> window =
2280 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2281 window->setFrame(Rect(0, 0, 200, 200));
2282
2283 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002285
2286 // Start hovering in the window
2287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2288 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2289 .build());
2290 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2291
2292 // Now, an obscuring window appears!
2293 sp<FakeWindowHandle> obscuringWindow =
2294 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2295 ADISPLAY_ID_DEFAULT,
2296 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2297 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2298 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2299 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2300 obscuringWindow->setNoInputChannel(true);
2301 obscuringWindow->setFocusable(false);
2302 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002303 mDispatcher->onWindowInfosChanged(
2304 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002305
2306 // While this new obscuring window is present, the hovering is stopped
2307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2308 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2309 .build());
2310 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2311
2312 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002313 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002314
2315 // And a new hover gesture starts.
2316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2317 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2318 .build());
2319 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2320}
2321
2322/**
2323 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2324 * the obscuring window.
2325 */
2326TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2328 sp<FakeWindowHandle> window =
2329 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2330 window->setFrame(Rect(0, 0, 200, 200));
2331
2332 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002333 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002334
2335 // Start hovering in the window
2336 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2337 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2338 .build());
2339 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2340
2341 // Now, an obscuring window appears!
2342 sp<FakeWindowHandle> obscuringWindow =
2343 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2344 ADISPLAY_ID_DEFAULT,
2345 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2346 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2347 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2348 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2349 obscuringWindow->setNoInputChannel(true);
2350 obscuringWindow->setFocusable(false);
2351 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002352 mDispatcher->onWindowInfosChanged(
2353 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002354
2355 // While this new obscuring window is present, the hovering continues. The event can't go to the
2356 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2357 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2358 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2359 .build());
2360 obscuringWindow->assertNoEvents();
2361 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2362
2363 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002364 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002365
2366 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2367 // so it should generate a HOVER_ENTER
2368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2370 .build());
2371 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2372
2373 // Now the MOVE should be getting dispatched normally
2374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2376 .build());
2377 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2378}
2379
2380/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002381 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2382 * events are delivered to the window.
2383 */
2384TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2386 sp<FakeWindowHandle> window =
2387 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2388 window->setFrame(Rect(0, 0, 200, 200));
2389 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2390
2391 // Start hovering in the window
2392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2393 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2394 .build());
2395 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2396
2397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2398 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2399 .build());
2400 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2401
2402 // Scroll with the mouse
2403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2404 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2405 .build());
2406 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2407}
2408
2409using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2410
2411/**
2412 * One window. Stylus down on the window. Next, touch from another device goes down.
2413 */
2414TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2416 sp<FakeWindowHandle> window =
2417 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2418 window->setFrame(Rect(0, 0, 200, 200));
2419
2420 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2421
2422 constexpr int32_t touchDeviceId = 4;
2423 constexpr int32_t stylusDeviceId = 2;
2424
2425 // Stylus down
2426 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2427 .deviceId(stylusDeviceId)
2428 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2429 .build());
2430 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2431
2432 // Touch down
2433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2434 .deviceId(touchDeviceId)
2435 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2436 .build());
2437 // Touch cancels stylus
2438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2439 WithCoords(100, 110)));
2440 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2441 WithCoords(140, 145)));
2442
2443 // Touch move
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2445 .deviceId(touchDeviceId)
2446 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2447 .build());
2448 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2449 WithCoords(141, 146)));
2450
2451 // Subsequent stylus movements are dropped
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2453 .deviceId(stylusDeviceId)
2454 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2455 .build());
2456 window->assertNoEvents();
2457}
2458
2459/**
2460 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2461 * down.
2462 * Similar test as above, but with added SPY window.
2463 */
2464TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2466 sp<FakeWindowHandle> window =
2467 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2468 sp<FakeWindowHandle> spyWindow =
2469 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2470 spyWindow->setFrame(Rect(0, 0, 200, 200));
2471 spyWindow->setTrustedOverlay(true);
2472 spyWindow->setSpy(true);
2473 window->setFrame(Rect(0, 0, 200, 200));
2474
2475 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2476
2477 constexpr int32_t touchDeviceId = 4;
2478 constexpr int32_t stylusDeviceId = 2;
2479
2480 // Stylus down
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2482 .deviceId(stylusDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2486 spyWindow->consumeMotionEvent(
2487 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2488
2489 // Touch down
2490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2491 .deviceId(touchDeviceId)
2492 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2493 .build());
2494
2495 // Touch move
2496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2497 .deviceId(touchDeviceId)
2498 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2499 .build());
2500 window->consumeMotionEvent(
2501 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2502 spyWindow->consumeMotionEvent(
2503 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2504 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2505 spyWindow->consumeMotionEvent(
2506 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2507 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2508 spyWindow->consumeMotionEvent(
2509 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2510 // Subsequent stylus movements are dropped
2511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2512 .deviceId(stylusDeviceId)
2513 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2514 .build());
2515
2516 window->assertNoEvents();
2517 spyWindow->assertNoEvents();
2518}
2519
2520/**
2521 * One window. Stylus hover on the window. Next, touch from another device goes down.
2522 */
2523TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2525 sp<FakeWindowHandle> window =
2526 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2527 window->setFrame(Rect(0, 0, 200, 200));
2528
2529 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2530
2531 constexpr int32_t touchDeviceId = 4;
2532 constexpr int32_t stylusDeviceId = 2;
2533
2534 // Stylus down on the window
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2536 .deviceId(stylusDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2538 .build());
2539 window->consumeMotionEvent(
2540 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2541
2542 // Touch down on window
2543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2544 .deviceId(touchDeviceId)
2545 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2546 .build());
2547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2548 .deviceId(touchDeviceId)
2549 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2550 .build());
2551 window->consumeMotionEvent(
2552 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2554 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2555 // Subsequent stylus movements are ignored
2556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2557 .deviceId(stylusDeviceId)
2558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2559 .build());
2560 window->assertNoEvents();
2561}
2562
2563/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002564 * Two windows: a window on the left and a window on the right.
2565 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2566 * down. Then, on the left window, also place second touch pointer down.
2567 * This test tries to reproduce a crash.
2568 * In the buggy implementation, second pointer down on the left window would cause a crash.
2569 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002570TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2572 sp<FakeWindowHandle> leftWindow =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2574 leftWindow->setFrame(Rect(0, 0, 200, 200));
2575
2576 sp<FakeWindowHandle> rightWindow =
2577 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2578 rightWindow->setFrame(Rect(200, 0, 400, 200));
2579
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002580 mDispatcher->onWindowInfosChanged(
2581 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002582
2583 const int32_t touchDeviceId = 4;
2584 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002585
2586 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2588 .deviceId(mouseDeviceId)
2589 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2590 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002591 leftWindow->consumeMotionEvent(
2592 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2593
2594 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002595 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2596 .deviceId(mouseDeviceId)
2597 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2598 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2599 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002600
2601 leftWindow->consumeMotionEvent(
2602 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2603 leftWindow->consumeMotionEvent(
2604 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2605
Prabir Pradhan678438e2023-04-13 19:32:51 +00002606 mDispatcher->notifyMotion(
2607 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2608 .deviceId(mouseDeviceId)
2609 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2610 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2611 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2612 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002613 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2614
2615 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2617 .deviceId(touchDeviceId)
2618 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2619 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002620 leftWindow->consumeMotionEvent(
2621 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002622 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2623
2624 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002625 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2626 .deviceId(touchDeviceId)
2627 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2628 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2629 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002630 leftWindow->consumeMotionEvent(
2631 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2632 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2633 // current implementation.
2634 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2635 rightWindow->consumeMotionEvent(
2636 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2637
2638 leftWindow->assertNoEvents();
2639 rightWindow->assertNoEvents();
2640}
2641
2642/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002643 * Two windows: a window on the left and a window on the right.
2644 * Mouse is hovered on the left window and stylus is hovered on the right window.
2645 */
2646TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2648 sp<FakeWindowHandle> leftWindow =
2649 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2650 leftWindow->setFrame(Rect(0, 0, 200, 200));
2651
2652 sp<FakeWindowHandle> rightWindow =
2653 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2654 rightWindow->setFrame(Rect(200, 0, 400, 200));
2655
2656 mDispatcher->onWindowInfosChanged(
2657 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2658
2659 const int32_t stylusDeviceId = 3;
2660 const int32_t mouseDeviceId = 6;
2661
2662 // Start hovering over the left window
2663 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2664 .deviceId(mouseDeviceId)
2665 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2666 .build());
2667 leftWindow->consumeMotionEvent(
2668 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2669
2670 // Stylus hovered on right window
2671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2672 .deviceId(stylusDeviceId)
2673 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2674 .build());
2675 leftWindow->consumeMotionEvent(
2676 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2677 rightWindow->consumeMotionEvent(
2678 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2679
2680 // Subsequent HOVER_MOVE events are dispatched correctly.
2681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2682 .deviceId(mouseDeviceId)
2683 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2684 .build());
2685 leftWindow->consumeMotionEvent(
2686 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2687 rightWindow->consumeMotionEvent(
2688 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2689
2690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2691 .deviceId(stylusDeviceId)
2692 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2693 .build());
2694 leftWindow->consumeMotionEvent(
2695 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2696 rightWindow->consumeMotionEvent(
2697 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2698
2699 leftWindow->assertNoEvents();
2700 rightWindow->assertNoEvents();
2701}
2702
2703/**
2704 * Three windows: a window on the left and a window on the right.
2705 * And a spy window that's positioned above all of them.
2706 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2707 * Check the stream that's received by the spy.
2708 */
2709TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2711
2712 sp<FakeWindowHandle> spyWindow =
2713 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2714 spyWindow->setFrame(Rect(0, 0, 400, 400));
2715 spyWindow->setTrustedOverlay(true);
2716 spyWindow->setSpy(true);
2717
2718 sp<FakeWindowHandle> leftWindow =
2719 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2720 leftWindow->setFrame(Rect(0, 0, 200, 200));
2721
2722 sp<FakeWindowHandle> rightWindow =
2723 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2724
2725 rightWindow->setFrame(Rect(200, 0, 400, 200));
2726
2727 mDispatcher->onWindowInfosChanged(
2728 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2729
2730 const int32_t stylusDeviceId = 1;
2731 const int32_t touchDeviceId = 2;
2732
2733 // Stylus down on the left window
2734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2735 .deviceId(stylusDeviceId)
2736 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2737 .build());
2738 leftWindow->consumeMotionEvent(
2739 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2740 spyWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2742
2743 // Touch down on the right window
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2745 .deviceId(touchDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2747 .build());
2748 leftWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2750 spyWindow->consumeMotionEvent(
2751 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2752 rightWindow->consumeMotionEvent(
2753 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2754 spyWindow->consumeMotionEvent(
2755 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2756
2757 // Stylus movements continue, but are ignored because the touch went down more recently.
2758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2759 .deviceId(stylusDeviceId)
2760 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2761 .build());
2762
2763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2764 .deviceId(touchDeviceId)
2765 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2766 .build());
2767 rightWindow->consumeMotionEvent(
2768 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2769 spyWindow->consumeMotionEvent(
2770 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2771
2772 spyWindow->assertNoEvents();
2773 leftWindow->assertNoEvents();
2774 rightWindow->assertNoEvents();
2775}
2776
2777/**
2778 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2779 * both.
2780 * Check hover in left window and touch down in the right window.
2781 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2782 */
2783TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2785
2786 sp<FakeWindowHandle> spyWindow =
2787 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2788 spyWindow->setFrame(Rect(0, 0, 400, 400));
2789 spyWindow->setTrustedOverlay(true);
2790 spyWindow->setSpy(true);
2791
2792 sp<FakeWindowHandle> leftWindow =
2793 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2794 leftWindow->setFrame(Rect(0, 0, 200, 200));
2795
2796 sp<FakeWindowHandle> rightWindow =
2797 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2798 rightWindow->setFrame(Rect(200, 0, 400, 200));
2799
2800 mDispatcher->onWindowInfosChanged(
2801 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2802
2803 const int32_t stylusDeviceId = 1;
2804 const int32_t touchDeviceId = 2;
2805
2806 // Stylus hover on the left window
2807 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2808 .deviceId(stylusDeviceId)
2809 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2810 .build());
2811 leftWindow->consumeMotionEvent(
2812 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2813 spyWindow->consumeMotionEvent(
2814 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2815
2816 // Touch down on the right window.
2817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2818 .deviceId(touchDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2820 .build());
2821 leftWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2823 spyWindow->consumeMotionEvent(
2824 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2825 spyWindow->consumeMotionEvent(
2826 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2827 rightWindow->consumeMotionEvent(
2828 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2829
2830 // Stylus movements continue, but are ignored because the touch is down.
2831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2832 .deviceId(stylusDeviceId)
2833 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2834 .build());
2835
2836 // Touch movements continue. They should be delivered to the right window and to the spy
2837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2838 .deviceId(touchDeviceId)
2839 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2840 .build());
2841 spyWindow->consumeMotionEvent(
2842 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2843 rightWindow->consumeMotionEvent(
2844 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2845
2846 spyWindow->assertNoEvents();
2847 leftWindow->assertNoEvents();
2848 rightWindow->assertNoEvents();
2849}
2850
2851/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 * On a single window, use two different devices: mouse and touch.
2853 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2854 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2855 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2856 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2857 * represent a new gesture.
2858 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002859TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2861 sp<FakeWindowHandle> window =
2862 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2863 window->setFrame(Rect(0, 0, 400, 400));
2864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002865 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002866
2867 const int32_t touchDeviceId = 4;
2868 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002869
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002870 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2872 .deviceId(touchDeviceId)
2873 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2874 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002875 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2877 .deviceId(touchDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2879 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2880 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002881 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002882 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2883 .deviceId(touchDeviceId)
2884 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2885 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2886 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002887 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2888 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2889 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2890
2891 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2893 .deviceId(mouseDeviceId)
2894 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2895 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002897
2898 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002899 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002900 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2901
Prabir Pradhan678438e2023-04-13 19:32:51 +00002902 mDispatcher->notifyMotion(
2903 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2904 .deviceId(mouseDeviceId)
2905 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2906 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2907 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2908 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002909 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2910
2911 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002912 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2913 .deviceId(touchDeviceId)
2914 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2915 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2916 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002917 // Since we already canceled this touch gesture, it will be ignored until a completely new
2918 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2919 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2920 // However, mouse movements should continue to work.
2921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2922 .deviceId(mouseDeviceId)
2923 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2924 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2925 .build());
2926 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2927
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002928 window->assertNoEvents();
2929}
2930
2931/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002932 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2933 * the injected event.
2934 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2937 sp<FakeWindowHandle> window =
2938 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2939 window->setFrame(Rect(0, 0, 400, 400));
2940
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002941 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002942
2943 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002944 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2945 // completion.
2946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002947 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002948 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2949 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002951 .build()));
2952 window->consumeMotionEvent(
2953 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2954
2955 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2956 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2958 .deviceId(touchDeviceId)
2959 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2960 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002961
2962 window->consumeMotionEvent(
2963 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2964 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2965}
2966
2967/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002968 * This test is similar to the test above, but the sequence of injected events is different.
2969 *
2970 * Two windows: a window on the left and a window on the right.
2971 * Mouse is hovered over the left window.
2972 * Next, we tap on the left window, where the cursor was last seen.
2973 *
2974 * After that, we inject one finger down onto the right window, and then a second finger down onto
2975 * the left window.
2976 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2977 * window (first), and then another on the left window (second).
2978 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2979 * In the buggy implementation, second finger down on the left window would cause a crash.
2980 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002981TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2983 sp<FakeWindowHandle> leftWindow =
2984 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2985 leftWindow->setFrame(Rect(0, 0, 200, 200));
2986
2987 sp<FakeWindowHandle> rightWindow =
2988 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2989 rightWindow->setFrame(Rect(200, 0, 400, 200));
2990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002991 mDispatcher->onWindowInfosChanged(
2992 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002993
2994 const int32_t mouseDeviceId = 6;
2995 const int32_t touchDeviceId = 4;
2996 // Hover over the left window. Keep the cursor there.
2997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002998 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002999 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3000 AINPUT_SOURCE_MOUSE)
3001 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003003 .build()));
3004 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3005
3006 // Tap on left window
3007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003008 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003009 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3010 AINPUT_SOURCE_TOUCHSCREEN)
3011 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003012 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003013 .build()));
3014
3015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003016 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003017 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3018 AINPUT_SOURCE_TOUCHSCREEN)
3019 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003020 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003021 .build()));
3022 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3023 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3024 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3025
3026 // First finger down on right window
3027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003028 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003029 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3030 AINPUT_SOURCE_TOUCHSCREEN)
3031 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003032 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003033 .build()));
3034 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3035
3036 // Second finger down on the left window
3037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003038 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003039 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3040 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003041 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3042 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003043 .build()));
3044 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3045 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3046
3047 // No more events
3048 leftWindow->assertNoEvents();
3049 rightWindow->assertNoEvents();
3050}
3051
3052/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003053 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3054 * While the touch is down, new hover events from the stylus device should be ignored. After the
3055 * touch is gone, stylus hovering should start working again.
3056 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003057TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3059 sp<FakeWindowHandle> window =
3060 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3061 window->setFrame(Rect(0, 0, 200, 200));
3062
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003063 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003064
3065 const int32_t stylusDeviceId = 5;
3066 const int32_t touchDeviceId = 4;
3067 // Start hovering with stylus
3068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003069 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003070 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003071 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003072 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003073 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003075
3076 // Finger down on the window
3077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003078 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003079 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003080 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003081 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003082 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003083 window->consumeMotionEvent(
3084 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3085 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003086
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003087 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003088 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003089 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003090 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3091 AINPUT_SOURCE_STYLUS)
3092 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003093 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003094 .build()));
3095 // No event should be sent. This event should be ignored because a pointer from another device
3096 // is already down.
3097
3098 // Lift up the finger
3099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003100 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003101 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3102 AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003105 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003106 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003107
3108 // Now that the touch is gone, stylus hovering should start working again
3109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003110 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003111 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3112 AINPUT_SOURCE_STYLUS)
3113 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003114 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003115 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003116 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3117 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003118 window->assertNoEvents();
3119}
3120
3121/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122 * A spy window above a window with no input channel.
3123 * Start hovering with a stylus device, and then tap with it.
3124 * Ensure spy window receives the entire sequence.
3125 */
3126TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3128 sp<FakeWindowHandle> spyWindow =
3129 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3130 spyWindow->setFrame(Rect(0, 0, 200, 200));
3131 spyWindow->setTrustedOverlay(true);
3132 spyWindow->setSpy(true);
3133 sp<FakeWindowHandle> window =
3134 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3135 window->setNoInputChannel(true);
3136 window->setFrame(Rect(0, 0, 200, 200));
3137
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003138 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3142 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3143 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003144 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3145 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3147 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3148 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003149 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3150
3151 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3153 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3154 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3156
3157 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3159 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3160 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003161 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3162
3163 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003164 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3165 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3166 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003167 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3168 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003169 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3170 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3171 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003172 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3173
3174 // No more events
3175 spyWindow->assertNoEvents();
3176 window->assertNoEvents();
3177}
3178
3179/**
3180 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3181 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3182 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3183 * While the mouse is down, new move events from the touch device should be ignored.
3184 */
3185TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3187 sp<FakeWindowHandle> spyWindow =
3188 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3189 spyWindow->setFrame(Rect(0, 0, 200, 200));
3190 spyWindow->setTrustedOverlay(true);
3191 spyWindow->setSpy(true);
3192 sp<FakeWindowHandle> window =
3193 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3194 window->setFrame(Rect(0, 0, 200, 200));
3195
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003196 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003197
3198 const int32_t mouseDeviceId = 7;
3199 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003200
3201 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003202 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3203 .deviceId(mouseDeviceId)
3204 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3205 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003206 spyWindow->consumeMotionEvent(
3207 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3208 window->consumeMotionEvent(
3209 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3210
3211 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3213 .deviceId(touchDeviceId)
3214 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3215 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003216 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3218 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3219 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3220
Prabir Pradhan678438e2023-04-13 19:32:51 +00003221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3222 .deviceId(touchDeviceId)
3223 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3224 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003225 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3226 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3227
3228 // Pilfer the stream
3229 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3230 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3231
Prabir Pradhan678438e2023-04-13 19:32:51 +00003232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3233 .deviceId(touchDeviceId)
3234 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3235 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003236 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3237
3238 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003239 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3240 .deviceId(mouseDeviceId)
3241 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3243 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003244
3245 spyWindow->consumeMotionEvent(
3246 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3247 spyWindow->consumeMotionEvent(
3248 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3249 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3250
Prabir Pradhan678438e2023-04-13 19:32:51 +00003251 mDispatcher->notifyMotion(
3252 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3253 .deviceId(mouseDeviceId)
3254 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3255 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3257 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003258 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3259 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3260
3261 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003262 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3263 .deviceId(mouseDeviceId)
3264 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3265 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3266 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003267 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3268 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3269
3270 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3272 .deviceId(touchDeviceId)
3273 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3274 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003275
3276 // No more events
3277 spyWindow->assertNoEvents();
3278 window->assertNoEvents();
3279}
3280
3281/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003282 * On the display, have a single window, and also an area where there's no window.
3283 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3284 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3285 */
3286TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3288 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003289 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003290
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003292
3293 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003294 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003295
3296 mDispatcher->waitForIdle();
3297 window->assertNoEvents();
3298
3299 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003300 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003301 mDispatcher->waitForIdle();
3302 window->consumeMotionDown();
3303}
3304
3305/**
3306 * Same test as above, but instead of touching the empty space, the first touch goes to
3307 * non-touchable window.
3308 */
3309TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3311 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003312 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003313 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3314 window1->setTouchable(false);
3315 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003316 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003317 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3318
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003319 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003320
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003321 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003322 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003323
3324 mDispatcher->waitForIdle();
3325 window1->assertNoEvents();
3326 window2->assertNoEvents();
3327
3328 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003329 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003330 mDispatcher->waitForIdle();
3331 window2->consumeMotionDown();
3332}
3333
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003334/**
3335 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3336 * to the event time of the first ACTION_DOWN sent to the particular window.
3337 */
3338TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3339 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3340 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003341 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003342 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3343 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003344 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003345 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3346
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003347 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003348
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003349 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003350 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003351
3352 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003353
3354 MotionEvent* motionEvent1 = window1->consumeMotion();
3355 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003356 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3358 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003359
3360 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003361 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003362 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003363 MotionEvent* motionEvent2 = window2->consumeMotion();
3364 ASSERT_NE(motionEvent2, nullptr);
3365 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003366 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003368
3369 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003370 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003371 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003372 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003373
3374 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003375 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003376 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003377 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003378
3379 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3380 window1->consumeMotionMove();
3381 window1->assertNoEvents();
3382
3383 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003384 mDispatcher->notifyMotion(
3385 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003386 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003387 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003388
Prabir Pradhan678438e2023-04-13 19:32:51 +00003389 mDispatcher->notifyMotion(
3390 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003391 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003392 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003393}
3394
Garfield Tandf26e862020-07-01 20:18:19 -07003395TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003397 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003398 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003399 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003400 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003401 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003402 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003403
3404 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3405
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003406 mDispatcher->onWindowInfosChanged(
3407 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003408
3409 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003411 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003412 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3413 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003414 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003415 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003416 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003417
3418 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003420 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003421 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3422 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003423 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003424 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003425 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3426 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003427
3428 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003430 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003431 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3432 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003433 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003434 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003435 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3436 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003437
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003439 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003440 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3441 AINPUT_SOURCE_MOUSE)
3442 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3443 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003444 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003445 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003446 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003449 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003450 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3451 AINPUT_SOURCE_MOUSE)
3452 .buttonState(0)
3453 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003454 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003455 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003456 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003457
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003459 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003460 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3461 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003462 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003463 .build()));
3464 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3465
3466 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003468 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003469 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3470 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003472 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003473 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003474
3475 // No more events
3476 windowLeft->assertNoEvents();
3477 windowRight->assertNoEvents();
3478}
3479
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003480/**
3481 * Put two fingers down (and don't release them) and click the mouse button.
3482 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3483 * currently active gesture should be canceled, and the new one should proceed.
3484 */
3485TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3487 sp<FakeWindowHandle> window =
3488 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3489 window->setFrame(Rect(0, 0, 600, 800));
3490
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003491 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003492
3493 const int32_t touchDeviceId = 4;
3494 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003495
3496 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3498 .deviceId(touchDeviceId)
3499 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3500 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003501
Prabir Pradhan678438e2023-04-13 19:32:51 +00003502 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3503 .deviceId(touchDeviceId)
3504 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3505 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3506 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003507 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3508 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3509
3510 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3512 .deviceId(mouseDeviceId)
3513 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3514 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003516 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3517 WithPointerCount(2u)));
3518 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3519
Prabir Pradhan678438e2023-04-13 19:32:51 +00003520 mDispatcher->notifyMotion(
3521 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3522 .deviceId(mouseDeviceId)
3523 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3524 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3525 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003527 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3528
3529 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3530 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3532 .deviceId(touchDeviceId)
3533 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3534 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3535 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003536 window->assertNoEvents();
3537}
3538
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003539TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3541
3542 sp<FakeWindowHandle> spyWindow =
3543 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3544 spyWindow->setFrame(Rect(0, 0, 600, 800));
3545 spyWindow->setTrustedOverlay(true);
3546 spyWindow->setSpy(true);
3547 sp<FakeWindowHandle> window =
3548 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3549 window->setFrame(Rect(0, 0, 600, 800));
3550
3551 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003552 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003553
3554 // Send mouse cursor to the window
3555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003556 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003557 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3558 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003559 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003560 .build()));
3561
3562 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3563 WithSource(AINPUT_SOURCE_MOUSE)));
3564 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3565 WithSource(AINPUT_SOURCE_MOUSE)));
3566
3567 window->assertNoEvents();
3568 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003569}
3570
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003571TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3573
3574 sp<FakeWindowHandle> spyWindow =
3575 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3576 spyWindow->setFrame(Rect(0, 0, 600, 800));
3577 spyWindow->setTrustedOverlay(true);
3578 spyWindow->setSpy(true);
3579 sp<FakeWindowHandle> window =
3580 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3581 window->setFrame(Rect(0, 0, 600, 800));
3582
3583 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003584 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003585
3586 // Send mouse cursor to the window
3587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003588 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003589 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3590 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003592 .build()));
3593
3594 // Move mouse cursor
3595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003596 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003597 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3598 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003599 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003600 .build()));
3601
3602 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3603 WithSource(AINPUT_SOURCE_MOUSE)));
3604 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3605 WithSource(AINPUT_SOURCE_MOUSE)));
3606 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3607 WithSource(AINPUT_SOURCE_MOUSE)));
3608 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3609 WithSource(AINPUT_SOURCE_MOUSE)));
3610 // Touch down on the window
3611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003612 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003613 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3614 AINPUT_SOURCE_TOUCHSCREEN)
3615 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003616 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003617 .build()));
3618 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3619 WithSource(AINPUT_SOURCE_MOUSE)));
3620 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3621 WithSource(AINPUT_SOURCE_MOUSE)));
3622 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3623 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3624 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3625 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3626
3627 // pilfer the motion, retaining the gesture on the spy window.
3628 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3629 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3630 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3631
3632 // Touch UP on the window
3633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003634 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003635 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3636 AINPUT_SOURCE_TOUCHSCREEN)
3637 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003638 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003639 .build()));
3640 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3641 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3642
3643 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3644 // to send a new gesture. It should again go to both windows (spy and the window below), just
3645 // like the first gesture did, before pilfering. The window configuration has not changed.
3646
3647 // One more tap - DOWN
3648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003649 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003650 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3651 AINPUT_SOURCE_TOUCHSCREEN)
3652 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003653 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003654 .build()));
3655 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3656 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3657 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3658 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3659
3660 // Touch UP on the window
3661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003662 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003663 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3664 AINPUT_SOURCE_TOUCHSCREEN)
3665 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003666 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003667 .build()));
3668 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3669 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3670 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3671 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3672
3673 window->assertNoEvents();
3674 spyWindow->assertNoEvents();
3675}
3676
Garfield Tandf26e862020-07-01 20:18:19 -07003677// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3678// directly in this test.
3679TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003681 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003682 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003683 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003684
3685 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003688
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003690 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003691 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3692 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003693 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003694 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003695 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003696 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003698 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003699 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3700 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003701 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003702 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003703 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3704 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003705
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003707 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003708 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3709 AINPUT_SOURCE_MOUSE)
3710 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3711 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003712 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003713 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003714 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003715
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003717 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003718 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3719 AINPUT_SOURCE_MOUSE)
3720 .buttonState(0)
3721 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003722 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003723 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003724 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003725
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003727 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003728 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3729 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003730 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003731 .build()));
3732 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3733
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003734 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3735 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003737 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003738 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3739 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003740 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003741 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003742 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003743}
3744
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003745/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003746 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3747 * is generated.
3748 */
3749TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3751 sp<FakeWindowHandle> window =
3752 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3753 window->setFrame(Rect(0, 0, 1200, 800));
3754
3755 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003758
3759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003760 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003761 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3762 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003763 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003764 .build()));
3765 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3766
3767 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003768 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003769 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3770}
3771
3772/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003773 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3774 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003775TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
3776 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
3777 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07003778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3779 sp<FakeWindowHandle> window =
3780 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3781 window->setFrame(Rect(0, 0, 1200, 800));
3782
3783 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3784
3785 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3786
3787 MotionEventBuilder hoverEnterBuilder =
3788 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3789 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3790 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3792 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3794 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3795 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3796 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3797}
3798
3799/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003800 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3801 */
3802TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3804 sp<FakeWindowHandle> window =
3805 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3806 window->setFrame(Rect(0, 0, 100, 100));
3807
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003808 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003809
3810 const int32_t mouseDeviceId = 7;
3811 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003812
3813 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3815 .deviceId(mouseDeviceId)
3816 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3817 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003818 window->consumeMotionEvent(
3819 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3820
3821 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3823 .deviceId(touchDeviceId)
3824 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3825 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003826
3827 window->consumeMotionEvent(
3828 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3829 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3830}
3831
3832/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003833 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003834 * The tap causes a HOVER_EXIT event to be generated because the current event
3835 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003836 */
3837TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3839 sp<FakeWindowHandle> window =
3840 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3841 window->setFrame(Rect(0, 0, 100, 100));
3842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3845 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3846 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003847 ASSERT_NO_FATAL_FAILURE(
3848 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3849 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003850
3851 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3853 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3854 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003855 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003856 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3857 WithSource(AINPUT_SOURCE_MOUSE))));
3858
3859 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003860 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3861 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3862
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3864 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3865 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003866 ASSERT_NO_FATAL_FAILURE(
3867 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3868 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3869}
3870
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003871TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3873 sp<FakeWindowHandle> windowDefaultDisplay =
3874 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3875 ADISPLAY_ID_DEFAULT);
3876 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3877 sp<FakeWindowHandle> windowSecondDisplay =
3878 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3879 SECOND_DISPLAY_ID);
3880 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3881
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003882 mDispatcher->onWindowInfosChanged(
3883 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003884
3885 // Set cursor position in window in default display and check that hover enter and move
3886 // events are generated.
3887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003888 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003889 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3890 AINPUT_SOURCE_MOUSE)
3891 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003892 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003893 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003894 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003895
3896 // Remove all windows in secondary display and check that no event happens on window in
3897 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003898 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3899
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003900 windowDefaultDisplay->assertNoEvents();
3901
3902 // Move cursor position in window in default display and check that only hover move
3903 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003904 mDispatcher->onWindowInfosChanged(
3905 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003907 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003908 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3909 AINPUT_SOURCE_MOUSE)
3910 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003912 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003913 windowDefaultDisplay->consumeMotionEvent(
3914 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3915 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003916 windowDefaultDisplay->assertNoEvents();
3917}
3918
Garfield Tan00f511d2019-06-12 16:55:40 -07003919TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003920 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003921
3922 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003923 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003924 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003925 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003926 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003927 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003928
3929 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3930
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003931 mDispatcher->onWindowInfosChanged(
3932 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003933
3934 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3935 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003937 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003938 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003939 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003940 windowRight->assertNoEvents();
3941}
3942
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003943TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003945 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3946 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003947 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003948
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003950 setFocusedWindow(window);
3951
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003952 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003953
Prabir Pradhan678438e2023-04-13 19:32:51 +00003954 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003955
3956 // Window should receive key down event.
3957 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3958
3959 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3960 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003961 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003962 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003963 AKEY_EVENT_FLAG_CANCELED);
3964}
3965
3966TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003968 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3969 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003970
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003971 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003972
Prabir Pradhan678438e2023-04-13 19:32:51 +00003973 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3974 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003975
3976 // Window should receive motion down event.
3977 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3978
3979 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3980 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003981 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003982 window->consumeMotionEvent(
3983 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003984}
3985
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003986TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3988 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3989 "Fake Window", ADISPLAY_ID_DEFAULT);
3990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003992
3993 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3994 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3995 .build());
3996
3997 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3998
3999 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4000 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4001 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4002
4003 // After the device has been reset, a new hovering stream can be sent to the window
4004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4005 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4006 .build());
4007 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4008}
4009
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004010TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004012 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4013 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004014 window->setFocusable(true);
4015
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004016 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004017 setFocusedWindow(window);
4018
4019 window->consumeFocusEvent(true);
4020
Prabir Pradhan678438e2023-04-13 19:32:51 +00004021 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004022 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4023 const nsecs_t injectTime = keyArgs.eventTime;
4024 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004025 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004026 // The dispatching time should be always greater than or equal to intercept key timeout.
4027 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4028 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4029 std::chrono::nanoseconds(interceptKeyTimeout).count());
4030}
4031
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004032/**
4033 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4034 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004035TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004037 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4038 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004039 window->setFocusable(true);
4040
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004041 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004042 setFocusedWindow(window);
4043
4044 window->consumeFocusEvent(true);
4045
Prabir Pradhan678438e2023-04-13 19:32:51 +00004046 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004047 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004048
4049 // Set a value that's significantly larger than the default consumption timeout. If the
4050 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4051 mFakePolicy->setInterceptKeyTimeout(600ms);
4052 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4053 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004054 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4055}
4056
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004057/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004058 * Two windows. First is a regular window. Second does not overlap with the first, and has
4059 * WATCH_OUTSIDE_TOUCH.
4060 * Both windows are owned by the same UID.
4061 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4062 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4063 */
4064TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4065 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004066 sp<FakeWindowHandle> window =
4067 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004068 window->setFrame(Rect{0, 0, 100, 100});
4069
4070 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004071 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004072 ADISPLAY_ID_DEFAULT);
4073 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4074 outsideWindow->setWatchOutsideTouch(true);
4075 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004076 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004077
4078 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004079 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4080 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4081 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004082 window->consumeMotionDown();
4083 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4084 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4085 outsideWindow->consumeMotionEvent(
4086 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4087}
4088
4089/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004090 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4091 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4092 * ACTION_OUTSIDE event is sent per gesture.
4093 */
4094TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4095 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004097 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4098 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004099 window->setWatchOutsideTouch(true);
4100 window->setFrame(Rect{0, 0, 100, 100});
4101 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004102 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4103 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004104 secondWindow->setFrame(Rect{100, 100, 200, 200});
4105 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004106 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4107 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004108 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004109 mDispatcher->onWindowInfosChanged(
4110 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004111
4112 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004113 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4114 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4115 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004116 window->assertNoEvents();
4117 secondWindow->assertNoEvents();
4118
4119 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4120 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004121 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4122 ADISPLAY_ID_DEFAULT,
4123 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004124 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4125 window->consumeMotionEvent(
4126 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004127 secondWindow->consumeMotionDown();
4128 thirdWindow->assertNoEvents();
4129
4130 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4131 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004132 mDispatcher->notifyMotion(
4133 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4134 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004135 window->assertNoEvents();
4136 secondWindow->consumeMotionMove();
4137 thirdWindow->consumeMotionDown();
4138}
4139
Prabir Pradhan814fe082022-07-22 20:22:18 +00004140TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4143 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004144 window->setFocusable(true);
4145
Patrick Williamsd828f302023-04-28 17:52:08 -05004146 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004147 setFocusedWindow(window);
4148
4149 window->consumeFocusEvent(true);
4150
Prabir Pradhan678438e2023-04-13 19:32:51 +00004151 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4152 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4153 mDispatcher->notifyKey(keyDown);
4154 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004155
4156 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4157 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4158
4159 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004160 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004161
4162 window->consumeFocusEvent(false);
4163
Prabir Pradhan678438e2023-04-13 19:32:51 +00004164 mDispatcher->notifyKey(keyDown);
4165 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004166 window->assertNoEvents();
4167}
4168
Arthur Hung96483742022-11-15 03:30:48 +00004169TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4171 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4172 "Fake Window", ADISPLAY_ID_DEFAULT);
4173 // Ensure window is non-split and have some transform.
4174 window->setPreventSplitting(true);
4175 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004177
4178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004179 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004180 {50, 50}))
4181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4182 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4183
4184 const MotionEvent secondFingerDownEvent =
4185 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4186 .displayId(ADISPLAY_ID_DEFAULT)
4187 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004188 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4189 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004190 .build();
4191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004192 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004193 InputEventInjectionSync::WAIT_FOR_RESULT))
4194 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4195
4196 const MotionEvent* event = window->consumeMotion();
4197 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4198 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4199 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4200 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4201 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4202}
4203
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004204/**
4205 * Two windows: a splittable and a non-splittable.
4206 * The non-splittable window shouldn't receive any "incomplete" gestures.
4207 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4208 * The second pointer should be dropped because the initial window is splittable, so it won't get
4209 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4210 * "incomplete" gestures.
4211 */
4212TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4214 sp<FakeWindowHandle> leftWindow =
4215 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4216 ADISPLAY_ID_DEFAULT);
4217 leftWindow->setPreventSplitting(false);
4218 leftWindow->setFrame(Rect(0, 0, 100, 100));
4219 sp<FakeWindowHandle> rightWindow =
4220 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4221 ADISPLAY_ID_DEFAULT);
4222 rightWindow->setPreventSplitting(true);
4223 rightWindow->setFrame(Rect(100, 100, 200, 200));
4224 mDispatcher->onWindowInfosChanged(
4225 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4226
4227 // Touch down on left, splittable window
4228 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4229 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4230 .build());
4231 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4232
4233 mDispatcher->notifyMotion(
4234 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4235 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4236 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4237 .build());
4238 leftWindow->assertNoEvents();
4239 rightWindow->assertNoEvents();
4240}
4241
Harry Cuttsb166c002023-05-09 13:06:05 +00004242TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4243 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4244 sp<FakeWindowHandle> window =
4245 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4246 window->setFrame(Rect(0, 0, 400, 400));
4247 sp<FakeWindowHandle> trustedOverlay =
4248 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4249 ADISPLAY_ID_DEFAULT);
4250 trustedOverlay->setSpy(true);
4251 trustedOverlay->setTrustedOverlay(true);
4252
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004253 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004254
4255 // Start a three-finger touchpad swipe
4256 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4257 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4258 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4259 .build());
4260 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4261 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4262 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4263 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4264 .build());
4265 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4266 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4267 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4268 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4269 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4270 .build());
4271
4272 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4273 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4274 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4275
4276 // Move the swipe a bit
4277 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4278 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4279 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4280 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4281 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4282 .build());
4283
4284 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4285
4286 // End the swipe
4287 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4288 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4289 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4290 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4291 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4292 .build());
4293 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4294 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4295 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4296 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4297 .build());
4298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4299 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4300 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4301 .build());
4302
4303 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4304 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4305 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4306
4307 window->assertNoEvents();
4308}
4309
4310TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4311 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4312 sp<FakeWindowHandle> window =
4313 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4314 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004315 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004316
4317 // Start a three-finger touchpad swipe
4318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4319 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4320 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4321 .build());
4322 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4323 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4324 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4325 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4326 .build());
4327 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4328 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4329 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4330 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4331 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4332 .build());
4333
4334 // Move the swipe a bit
4335 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4336 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4337 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4338 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4339 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4340 .build());
4341
4342 // End the swipe
4343 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4344 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4345 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4346 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4347 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4348 .build());
4349 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4350 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4351 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4352 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4353 .build());
4354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4355 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4356 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4357 .build());
4358
4359 window->assertNoEvents();
4360}
4361
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004362/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004363 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4364 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004365 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004366 */
4367TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4369 sp<FakeWindowHandle> window =
4370 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4371 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004372 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004373
4374 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4376 .downTime(baseTime + 10)
4377 .eventTime(baseTime + 10)
4378 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4379 .build());
4380
4381 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4382
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004383 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004384 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004385
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004386 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004387
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004388 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4389 .downTime(baseTime + 10)
4390 .eventTime(baseTime + 30)
4391 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4392 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4393 .build());
4394
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004395 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4396
4397 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004398 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4399 .downTime(baseTime + 10)
4400 .eventTime(baseTime + 40)
4401 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4402 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4403 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004404
4405 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4406
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4408 .downTime(baseTime + 10)
4409 .eventTime(baseTime + 50)
4410 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4411 .build());
4412
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004413 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4414
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4416 .downTime(baseTime + 60)
4417 .eventTime(baseTime + 60)
4418 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4419 .build());
4420
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004421 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004422}
4423
4424/**
Hu Guo771a7692023-09-17 20:51:08 +08004425 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4426 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4427 * its coordinates should be converted by the transform of the windows of target screen.
4428 */
4429TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4430 // This case will create a window and a spy window on the default display and mirror
4431 // window on the second display. cancel event is sent through spy window pilferPointers
4432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4433
4434 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4435 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4436 spyWindowDefaultDisplay->setTrustedOverlay(true);
4437 spyWindowDefaultDisplay->setSpy(true);
4438
4439 sp<FakeWindowHandle> windowDefaultDisplay =
4440 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4441 ADISPLAY_ID_DEFAULT);
4442 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4443
4444 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4445 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4446
4447 // Add the windows to the dispatcher
4448 mDispatcher->onWindowInfosChanged(
4449 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4450 *windowSecondDisplay->getInfo()},
4451 {},
4452 0,
4453 0});
4454
4455 // Send down to ADISPLAY_ID_DEFAULT
4456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4457 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4458 {100, 100}))
4459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4460
4461 spyWindowDefaultDisplay->consumeMotionDown();
4462 windowDefaultDisplay->consumeMotionDown();
4463
4464 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4465
4466 // windowDefaultDisplay gets cancel
4467 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4468 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4469
4470 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4471 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4472 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4473 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4474 EXPECT_EQ(100, event->getX(0));
4475 EXPECT_EQ(100, event->getY(0));
4476}
4477
4478/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004479 * Ensure the correct coordinate spaces are used by InputDispatcher.
4480 *
4481 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4482 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4483 * space.
4484 */
4485class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4486public:
4487 void SetUp() override {
4488 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004489 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004490 }
4491
4492 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4493 gui::DisplayInfo info;
4494 info.displayId = displayId;
4495 info.transform = transform;
4496 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004497 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004498 }
4499
4500 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4501 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004502 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004503 }
4504
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004505 void removeAllWindowsAndDisplays() {
4506 mDisplayInfos.clear();
4507 mWindowInfos.clear();
4508 }
4509
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004510 // Set up a test scenario where the display has a scaled projection and there are two windows
4511 // on the display.
4512 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4513 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4514 // respectively.
4515 ui::Transform displayTransform;
4516 displayTransform.set(2, 0, 0, 4);
4517 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4518
4519 std::shared_ptr<FakeApplicationHandle> application =
4520 std::make_shared<FakeApplicationHandle>();
4521
4522 // Add two windows to the display. Their frames are represented in the display space.
4523 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004524 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4525 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004526 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4527 addWindow(firstWindow);
4528
4529 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004530 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4531 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004532 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4533 addWindow(secondWindow);
4534 return {std::move(firstWindow), std::move(secondWindow)};
4535 }
4536
4537private:
4538 std::vector<gui::DisplayInfo> mDisplayInfos;
4539 std::vector<gui::WindowInfo> mWindowInfos;
4540};
4541
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004542TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004543 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4544 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004545 // selected so that if the hit test was performed with the point and the bounds being in
4546 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004547 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4548 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4549 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004550
4551 firstWindow->consumeMotionDown();
4552 secondWindow->assertNoEvents();
4553}
4554
4555// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4556// the event should be treated as being in the logical display space.
4557TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4558 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4559 // Send down to the first window. The point is represented in the logical display space. The
4560 // point is selected so that if the hit test was done in logical display space, then it would
4561 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004562 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004563 PointF{75 * 2, 55 * 4});
4564
4565 firstWindow->consumeMotionDown();
4566 secondWindow->assertNoEvents();
4567}
4568
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004569// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4570// event should be treated as being in the logical display space.
4571TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4572 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4573
4574 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4575 ui::Transform injectedEventTransform;
4576 injectedEventTransform.set(matrix);
4577 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4578 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4579
4580 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4581 .displayId(ADISPLAY_ID_DEFAULT)
4582 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004583 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004584 .x(untransformedPoint.x)
4585 .y(untransformedPoint.y))
4586 .build();
4587 event.transform(matrix);
4588
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004589 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004590 InputEventInjectionSync::WAIT_FOR_RESULT);
4591
4592 firstWindow->consumeMotionDown();
4593 secondWindow->assertNoEvents();
4594}
4595
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004596TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4597 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4598
4599 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004600 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4601 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4602 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004603
4604 firstWindow->assertNoEvents();
4605 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004606 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004607 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4608
4609 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4610 EXPECT_EQ(300, event->getRawX(0));
4611 EXPECT_EQ(880, event->getRawY(0));
4612
4613 // Ensure that the x and y values are in the window's coordinate space.
4614 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4615 // the logical display space. This will be the origin of the window space.
4616 EXPECT_EQ(100, event->getX(0));
4617 EXPECT_EQ(80, event->getY(0));
4618}
4619
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004620TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4621 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4622 // The monitor will always receive events in the logical display's coordinate space, because
4623 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004624 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004625
4626 // Send down to the first window.
4627 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4628 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4629 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4630 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4631
4632 // Second pointer goes down on second window.
4633 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4634 ADISPLAY_ID_DEFAULT,
4635 {PointF{50, 100}, PointF{150, 220}}));
4636 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4637 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4638 {1, PointF{300, 880}}};
4639 monitor.consumeMotionEvent(
4640 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4641
4642 mDispatcher->cancelCurrentTouch();
4643
4644 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4645 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4646 monitor.consumeMotionEvent(
4647 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4648}
4649
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004650TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4651 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4652
4653 // Send down to the first window.
4654 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4655 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4656 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4657
4658 // The pointer is transferred to the second window, and the second window receives it in the
4659 // correct coordinate space.
4660 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4661 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4662 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4663}
4664
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004665TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4666 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4667
4668 // Send hover move to the second window, and ensure it shows up as hover enter.
4669 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4670 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4671 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4672 WithCoords(100, 80), WithRawCoords(300, 880)));
4673
4674 // Touch down at the same location and ensure a hover exit is synthesized.
4675 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4676 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4677 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4678 WithRawCoords(300, 880)));
4679 secondWindow->consumeMotionEvent(
4680 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4681 secondWindow->assertNoEvents();
4682 firstWindow->assertNoEvents();
4683}
4684
4685TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4686 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4687
4688 // Send hover enter to second window
4689 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4690 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4691 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4692 WithCoords(100, 80), WithRawCoords(300, 880)));
4693
4694 mDispatcher->cancelCurrentTouch();
4695
4696 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4697 WithRawCoords(300, 880)));
4698 secondWindow->assertNoEvents();
4699 firstWindow->assertNoEvents();
4700}
4701
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004702/** Ensure consistent behavior of InputDispatcher in all orientations. */
4703class InputDispatcherDisplayOrientationFixture
4704 : public InputDispatcherDisplayProjectionTest,
4705 public ::testing::WithParamInterface<ui::Rotation> {};
4706
4707// This test verifies the touchable region of a window for all rotations of the display by tapping
4708// in different locations on the display, specifically points close to the four corners of a
4709// window.
4710TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4711 constexpr static int32_t displayWidth = 400;
4712 constexpr static int32_t displayHeight = 800;
4713
4714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4715
4716 const auto rotation = GetParam();
4717
4718 // Set up the display with the specified rotation.
4719 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4720 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4721 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4722 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4723 logicalDisplayWidth, logicalDisplayHeight);
4724 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4725
4726 // Create a window with its bounds determined in the logical display.
4727 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4728 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4729 sp<FakeWindowHandle> window =
4730 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4731 window->setFrame(frameInDisplay, displayTransform);
4732 addWindow(window);
4733
4734 // The following points in logical display space should be inside the window.
4735 static const std::array<vec2, 4> insidePoints{
4736 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4737 for (const auto pointInsideWindow : insidePoints) {
4738 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4739 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004740 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4741 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4742 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004743 window->consumeMotionDown();
4744
Prabir Pradhan678438e2023-04-13 19:32:51 +00004745 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4746 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4747 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004748 window->consumeMotionUp();
4749 }
4750
4751 // The following points in logical display space should be outside the window.
4752 static const std::array<vec2, 5> outsidePoints{
4753 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4754 for (const auto pointOutsideWindow : outsidePoints) {
4755 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4756 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004757 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4758 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4759 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004760
Prabir Pradhan678438e2023-04-13 19:32:51 +00004761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4762 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4763 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004764 }
4765 window->assertNoEvents();
4766}
4767
4768// Run the precision tests for all rotations.
4769INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4770 InputDispatcherDisplayOrientationFixture,
4771 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4772 ui::ROTATION_270),
4773 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4774 return ftl::enum_string(testParamInfo.param);
4775 });
4776
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004777using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4778 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004779
4780class TransferTouchFixture : public InputDispatcherTest,
4781 public ::testing::WithParamInterface<TransferFunction> {};
4782
4783TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004785
4786 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004787 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004788 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4789 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004790 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004791 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004792 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4793 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004794 sp<FakeWindowHandle> wallpaper =
4795 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4796 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004797 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004798 mDispatcher->onWindowInfosChanged(
4799 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004800
4801 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004802 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4803 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004804
Svet Ganov5d3bc372020-01-26 23:11:07 -08004805 // Only the first window should get the down event
4806 firstWindow->consumeMotionDown();
4807 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004808 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004809
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004810 // Transfer touch to the second window
4811 TransferFunction f = GetParam();
4812 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4813 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004814 // The first window gets cancel and the second gets down
4815 firstWindow->consumeMotionCancel();
4816 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004817 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004818
4819 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004820 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4821 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004822 // The first window gets no events and the second gets up
4823 firstWindow->assertNoEvents();
4824 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004825 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004826}
4827
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004828/**
4829 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4830 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4831 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4832 * natural to the user.
4833 * In this test, we are sending a pointer to both spy window and first window. We then try to
4834 * transfer touch to the second window. The dispatcher should identify the first window as the
4835 * one that should lose the gesture, and therefore the action should be to move the gesture from
4836 * the first window to the second.
4837 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4838 * the other API, as well.
4839 */
4840TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4842
4843 // Create a couple of windows + a spy window
4844 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004845 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004846 spyWindow->setTrustedOverlay(true);
4847 spyWindow->setSpy(true);
4848 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004849 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004850 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004851 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004852
4853 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004854 mDispatcher->onWindowInfosChanged(
4855 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004856
4857 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004858 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4859 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004860 // Only the first window and spy should get the down event
4861 spyWindow->consumeMotionDown();
4862 firstWindow->consumeMotionDown();
4863
4864 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4865 // if f === 'transferTouch'.
4866 TransferFunction f = GetParam();
4867 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4868 ASSERT_TRUE(success);
4869 // The first window gets cancel and the second gets down
4870 firstWindow->consumeMotionCancel();
4871 secondWindow->consumeMotionDown();
4872
4873 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004874 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4875 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004876 // The first window gets no events and the second+spy get up
4877 firstWindow->assertNoEvents();
4878 spyWindow->consumeMotionUp();
4879 secondWindow->consumeMotionUp();
4880}
4881
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004882TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004884
4885 PointF touchPoint = {10, 10};
4886
4887 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004888 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004889 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4890 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004891 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004892 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004893 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4894 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004895 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004896
4897 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004898 mDispatcher->onWindowInfosChanged(
4899 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004900
4901 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004902 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4903 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4904 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004905 // Only the first window should get the down event
4906 firstWindow->consumeMotionDown();
4907 secondWindow->assertNoEvents();
4908
4909 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004910 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4911 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004912 // Only the first window should get the pointer down event
4913 firstWindow->consumeMotionPointerDown(1);
4914 secondWindow->assertNoEvents();
4915
4916 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004917 TransferFunction f = GetParam();
4918 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4919 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004920 // The first window gets cancel and the second gets down and pointer down
4921 firstWindow->consumeMotionCancel();
4922 secondWindow->consumeMotionDown();
4923 secondWindow->consumeMotionPointerDown(1);
4924
4925 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004926 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4927 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004928 // The first window gets nothing and the second gets pointer up
4929 firstWindow->assertNoEvents();
4930 secondWindow->consumeMotionPointerUp(1);
4931
4932 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004933 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4934 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004935 // The first window gets nothing and the second gets up
4936 firstWindow->assertNoEvents();
4937 secondWindow->consumeMotionUp();
4938}
4939
Arthur Hungc539dbb2022-12-08 07:45:36 +00004940TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4941 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4942
4943 // Create a couple of windows
4944 sp<FakeWindowHandle> firstWindow =
4945 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4946 ADISPLAY_ID_DEFAULT);
4947 firstWindow->setDupTouchToWallpaper(true);
4948 sp<FakeWindowHandle> secondWindow =
4949 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4950 ADISPLAY_ID_DEFAULT);
4951 secondWindow->setDupTouchToWallpaper(true);
4952
4953 sp<FakeWindowHandle> wallpaper1 =
4954 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4955 wallpaper1->setIsWallpaper(true);
4956
4957 sp<FakeWindowHandle> wallpaper2 =
4958 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4959 wallpaper2->setIsWallpaper(true);
4960 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004961 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4962 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4963 {},
4964 0,
4965 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004966
4967 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004968 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4969 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004970
4971 // Only the first window should get the down event
4972 firstWindow->consumeMotionDown();
4973 secondWindow->assertNoEvents();
4974 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4975 wallpaper2->assertNoEvents();
4976
4977 // Transfer touch focus to the second window
4978 TransferFunction f = GetParam();
4979 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4980 ASSERT_TRUE(success);
4981
4982 // The first window gets cancel and the second gets down
4983 firstWindow->consumeMotionCancel();
4984 secondWindow->consumeMotionDown();
4985 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4986 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4987
4988 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004989 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4990 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004991 // The first window gets no events and the second gets up
4992 firstWindow->assertNoEvents();
4993 secondWindow->consumeMotionUp();
4994 wallpaper1->assertNoEvents();
4995 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4996}
4997
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004998// For the cases of single pointer touch and two pointers non-split touch, the api's
4999// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5000// for the case where there are multiple pointers split across several windows.
5001INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5002 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005003 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5004 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005005 return dispatcher->transferTouch(destChannelToken,
5006 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005007 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005008 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5009 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005010 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005011 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005012 }));
5013
Svet Ganov5d3bc372020-01-26 23:11:07 -08005014TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005016
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005017 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005018 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5019 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005020 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005021
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005022 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005023 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5024 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005025 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005026
5027 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005028 mDispatcher->onWindowInfosChanged(
5029 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005030
5031 PointF pointInFirst = {300, 200};
5032 PointF pointInSecond = {300, 600};
5033
5034 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005035 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5036 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5037 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005038 // Only the first window should get the down event
5039 firstWindow->consumeMotionDown();
5040 secondWindow->assertNoEvents();
5041
5042 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005043 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5044 ADISPLAY_ID_DEFAULT,
5045 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005046 // The first window gets a move and the second a down
5047 firstWindow->consumeMotionMove();
5048 secondWindow->consumeMotionDown();
5049
5050 // Transfer touch focus to the second window
5051 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5052 // The first window gets cancel and the new gets pointer down (it already saw down)
5053 firstWindow->consumeMotionCancel();
5054 secondWindow->consumeMotionPointerDown(1);
5055
5056 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005057 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5058 ADISPLAY_ID_DEFAULT,
5059 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005060 // The first window gets nothing and the second gets pointer up
5061 firstWindow->assertNoEvents();
5062 secondWindow->consumeMotionPointerUp(1);
5063
5064 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005065 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5066 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005067 // The first window gets nothing and the second gets up
5068 firstWindow->assertNoEvents();
5069 secondWindow->consumeMotionUp();
5070}
5071
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005072// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5073// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5074// touch is not supported, so the touch should continue on those windows and the transferred-to
5075// window should get nothing.
5076TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5078
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005079 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005080 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5081 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005082 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005083
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005084 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005085 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5086 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005087 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005088
5089 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005090 mDispatcher->onWindowInfosChanged(
5091 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005092
5093 PointF pointInFirst = {300, 200};
5094 PointF pointInSecond = {300, 600};
5095
5096 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005097 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5098 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5099 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005100 // Only the first window should get the down event
5101 firstWindow->consumeMotionDown();
5102 secondWindow->assertNoEvents();
5103
5104 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005105 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5106 ADISPLAY_ID_DEFAULT,
5107 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005108 // The first window gets a move and the second a down
5109 firstWindow->consumeMotionMove();
5110 secondWindow->consumeMotionDown();
5111
5112 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005113 const bool transferred =
5114 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005115 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5116 ASSERT_FALSE(transferred);
5117 firstWindow->assertNoEvents();
5118 secondWindow->assertNoEvents();
5119
5120 // The rest of the dispatch should proceed as normal
5121 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005122 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5123 ADISPLAY_ID_DEFAULT,
5124 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005125 // The first window gets MOVE and the second gets pointer up
5126 firstWindow->consumeMotionMove();
5127 secondWindow->consumeMotionUp();
5128
5129 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005130 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5131 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005132 // The first window gets nothing and the second gets up
5133 firstWindow->consumeMotionUp();
5134 secondWindow->assertNoEvents();
5135}
5136
Arthur Hungabbb9d82021-09-01 14:52:30 +00005137// This case will create two windows and one mirrored window on the default display and mirror
5138// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5139// the windows info of second display before default display.
5140TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5142 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005143 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005144 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005145 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005146 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005147 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005148
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005149 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005150 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005151
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005152 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005153 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005154
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005155 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005156 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005157
5158 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005159 mDispatcher->onWindowInfosChanged(
5160 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5161 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5162 *secondWindowInPrimary->getInfo()},
5163 {},
5164 0,
5165 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005166
5167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005168 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005169 {50, 50}))
5170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5171
5172 // Window should receive motion event.
5173 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5174
5175 // Transfer touch focus
5176 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5177 secondWindowInPrimary->getToken()));
5178 // The first window gets cancel.
5179 firstWindowInPrimary->consumeMotionCancel();
5180 secondWindowInPrimary->consumeMotionDown();
5181
5182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005183 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005184 ADISPLAY_ID_DEFAULT, {150, 50}))
5185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5186 firstWindowInPrimary->assertNoEvents();
5187 secondWindowInPrimary->consumeMotionMove();
5188
5189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005190 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005191 {150, 50}))
5192 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5193 firstWindowInPrimary->assertNoEvents();
5194 secondWindowInPrimary->consumeMotionUp();
5195}
5196
5197// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5198// 'transferTouch' api.
5199TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5200 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5201 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005202 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005203 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005204 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005205 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005206 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005207
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005208 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005209 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005210
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005211 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005212 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005213
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005214 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005215 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005216
5217 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005218 mDispatcher->onWindowInfosChanged(
5219 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5220 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5221 *secondWindowInPrimary->getInfo()},
5222 {},
5223 0,
5224 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005225
5226 // Touch on second display.
5227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005228 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5229 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5231
5232 // Window should receive motion event.
5233 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5234
5235 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005236 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005237
5238 // The first window gets cancel.
5239 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5240 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5241
5242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005243 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005244 SECOND_DISPLAY_ID, {150, 50}))
5245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5246 firstWindowInPrimary->assertNoEvents();
5247 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5248
5249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005250 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005251 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5252 firstWindowInPrimary->assertNoEvents();
5253 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5254}
5255
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005256TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005258 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5259 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005260
Vishnu Nair47074b82020-08-14 11:54:47 -07005261 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005262 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005263 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005264
5265 window->consumeFocusEvent(true);
5266
Prabir Pradhan678438e2023-04-13 19:32:51 +00005267 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005268
5269 // Window should receive key down event.
5270 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005271
5272 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005273 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005274 mFakePolicy->assertUserActivityPoked();
5275}
5276
5277TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5279 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5280 "Fake Window", ADISPLAY_ID_DEFAULT);
5281
5282 window->setDisableUserActivity(true);
5283 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005285 setFocusedWindow(window);
5286
5287 window->consumeFocusEvent(true);
5288
5289 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5290
5291 // Window should receive key down event.
5292 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5293
5294 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005295 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005296 mFakePolicy->assertUserActivityNotPoked();
5297}
5298
5299TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5301 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5302 "Fake Window", ADISPLAY_ID_DEFAULT);
5303
5304 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005306 setFocusedWindow(window);
5307
5308 window->consumeFocusEvent(true);
5309
5310 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5311 mDispatcher->waitForIdle();
5312
5313 // System key is not passed down
5314 window->assertNoEvents();
5315
5316 // Should have poked user activity
5317 mFakePolicy->assertUserActivityPoked();
5318}
5319
5320TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5322 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5323 "Fake Window", ADISPLAY_ID_DEFAULT);
5324
5325 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005326 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005327 setFocusedWindow(window);
5328
5329 window->consumeFocusEvent(true);
5330
5331 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5332 mDispatcher->waitForIdle();
5333
5334 // System key is not passed down
5335 window->assertNoEvents();
5336
5337 // Should have poked user activity
5338 mFakePolicy->assertUserActivityPoked();
5339}
5340
5341TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5343 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5344 "Fake Window", ADISPLAY_ID_DEFAULT);
5345
5346 window->setDisableUserActivity(true);
5347 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005349 setFocusedWindow(window);
5350
5351 window->consumeFocusEvent(true);
5352
5353 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5354 mDispatcher->waitForIdle();
5355
5356 // System key is not passed down
5357 window->assertNoEvents();
5358
5359 // Should have poked user activity
5360 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005361}
5362
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005363TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5365 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5366 "Fake Window", ADISPLAY_ID_DEFAULT);
5367
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005369
5370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005371 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005372 ADISPLAY_ID_DEFAULT, {100, 100}))
5373 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5374
5375 window->consumeMotionEvent(
5376 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5377
5378 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005379 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005380 mFakePolicy->assertUserActivityPoked();
5381}
5382
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005383TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005385 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5386 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005387
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005388 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005389
Prabir Pradhan678438e2023-04-13 19:32:51 +00005390 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005391 mDispatcher->waitForIdle();
5392
5393 window->assertNoEvents();
5394}
5395
5396// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5397TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005399 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5400 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005403
5404 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005405 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005406 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005407 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5408 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005409
5410 // Window should receive only the motion event
5411 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5412 window->assertNoEvents(); // Key event or focus event will not be received
5413}
5414
arthurhungea3f4fc2020-12-21 23:18:53 +08005415TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5417
arthurhungea3f4fc2020-12-21 23:18:53 +08005418 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005419 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5420 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005421 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005422
arthurhungea3f4fc2020-12-21 23:18:53 +08005423 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005424 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5425 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005426 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005427
5428 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005429 mDispatcher->onWindowInfosChanged(
5430 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005431
5432 PointF pointInFirst = {300, 200};
5433 PointF pointInSecond = {300, 600};
5434
5435 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005436 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5437 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5438 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005439 // Only the first window should get the down event
5440 firstWindow->consumeMotionDown();
5441 secondWindow->assertNoEvents();
5442
5443 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005444 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5445 ADISPLAY_ID_DEFAULT,
5446 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005447 // The first window gets a move and the second a down
5448 firstWindow->consumeMotionMove();
5449 secondWindow->consumeMotionDown();
5450
5451 // Send pointer cancel to the second window
5452 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005453 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005454 {pointInFirst, pointInSecond});
5455 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005456 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005457 // The first window gets move and the second gets cancel.
5458 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5459 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5460
5461 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005462 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5463 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005464 // The first window gets up and the second gets nothing.
5465 firstWindow->consumeMotionUp();
5466 secondWindow->assertNoEvents();
5467}
5468
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005469TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5471
5472 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005473 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005474 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005475 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5476 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5477 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5478
Harry Cutts33476232023-01-30 19:57:29 +00005479 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005480 window->assertNoEvents();
5481 mDispatcher->waitForIdle();
5482}
5483
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005484using InputDispatcherMonitorTest = InputDispatcherTest;
5485
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005486/**
5487 * Two entities that receive touch: A window, and a global monitor.
5488 * The touch goes to the window, and then the window disappears.
5489 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5490 * for the monitor, as well.
5491 * 1. foregroundWindow
5492 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5493 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005494TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5496 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005497 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005498
Prabir Pradhanfb549072023-10-05 19:17:36 +00005499 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005500
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005501 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005503 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005504 {100, 200}))
5505 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5506
5507 // Both the foreground window and the global monitor should receive the touch down
5508 window->consumeMotionDown();
5509 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5510
5511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005512 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005513 ADISPLAY_ID_DEFAULT, {110, 200}))
5514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5515
5516 window->consumeMotionMove();
5517 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5518
5519 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005520 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005521 window->consumeMotionCancel();
5522 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5523
5524 // If more events come in, there will be no more foreground window to send them to. This will
5525 // cause a cancel for the monitor, as well.
5526 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005527 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005528 ADISPLAY_ID_DEFAULT, {120, 200}))
5529 << "Injection should fail because the window was removed";
5530 window->assertNoEvents();
5531 // Global monitor now gets the cancel
5532 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5533}
5534
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005535TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005537 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5538 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005539 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005540
Prabir Pradhanfb549072023-10-05 19:17:36 +00005541 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005542
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005545 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005546 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005547 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005548}
5549
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005550TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005551 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005552
Chris Yea209fde2020-07-22 13:54:51 -07005553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005554 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5555 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005556 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005557
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005559 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005561 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005562 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005563
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005564 // Pilfer pointers from the monitor.
5565 // This should not do anything and the window should continue to receive events.
5566 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005567
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005568 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005569 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005570 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005571 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005572
5573 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5574 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005575}
5576
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005577TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005579 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5580 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005581 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005582 window->setWindowOffset(20, 40);
5583 window->setWindowTransform(0, 1, -1, 0);
5584
Prabir Pradhanfb549072023-10-05 19:17:36 +00005585 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005586
5587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005588 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005589 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5590 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5591 MotionEvent* event = monitor.consumeMotion();
5592 // Even though window has transform, gesture monitor must not.
5593 ASSERT_EQ(ui::Transform(), event->getTransform());
5594}
5595
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005596TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005598 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005599
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005600 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005601 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005602 << "Injection should fail if there is a monitor, but no touchable window";
5603 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005604}
5605
chaviw81e2bb92019-12-18 15:03:51 -08005606TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005608 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5609 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005610
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005612
5613 NotifyMotionArgs motionArgs =
5614 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5615 ADISPLAY_ID_DEFAULT);
5616
Prabir Pradhan678438e2023-04-13 19:32:51 +00005617 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005618 // Window should receive motion down event.
5619 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5620
5621 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005622 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005623 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5624 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5625 motionArgs.pointerCoords[0].getX() - 10);
5626
Prabir Pradhan678438e2023-04-13 19:32:51 +00005627 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005628 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005629 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005630}
5631
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005632/**
5633 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5634 * the device default right away. In the test scenario, we check both the default value,
5635 * and the action of enabling / disabling.
5636 */
5637TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005639 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5640 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005641 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005642
5643 // Set focused application.
5644 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005645 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005646
5647 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005648 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005649 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005650 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005651
5652 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005653 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005654 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005655 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005656
5657 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005658 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005659 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005660 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005661 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005663 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005664 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005665
5666 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005667 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005668 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005669 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005670
5671 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005672 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005673 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005674 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005675 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005676 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005677 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005678 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005679
5680 window->assertNoEvents();
5681}
5682
Gang Wange9087892020-01-07 12:17:14 -05005683TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005685 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5686 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005687
5688 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005689 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005690
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005691 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005692 setFocusedWindow(window);
5693
Harry Cutts33476232023-01-30 19:57:29 +00005694 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005695
Prabir Pradhan678438e2023-04-13 19:32:51 +00005696 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5697 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005698
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005699 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005700 ASSERT_NE(event, nullptr);
5701
5702 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5703 ASSERT_NE(verified, nullptr);
5704 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5705
5706 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5707 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5708 ASSERT_EQ(keyArgs.source, verified->source);
5709 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5710
5711 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5712
5713 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005714 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005715 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005716 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5717 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5718 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5719 ASSERT_EQ(0, verifiedKey.repeatCount);
5720}
5721
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005722TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005724 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5725 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005726
5727 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5728
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005729 ui::Transform transform;
5730 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5731
5732 gui::DisplayInfo displayInfo;
5733 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5734 displayInfo.transform = transform;
5735
Patrick Williamsd828f302023-04-28 17:52:08 -05005736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005737
Prabir Pradhan678438e2023-04-13 19:32:51 +00005738 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005739 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5740 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005741 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005742
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005743 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005744 ASSERT_NE(event, nullptr);
5745
5746 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5747 ASSERT_NE(verified, nullptr);
5748 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5749
5750 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5751 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5752 EXPECT_EQ(motionArgs.source, verified->source);
5753 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5754
5755 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5756
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005757 const vec2 rawXY =
5758 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5759 motionArgs.pointerCoords[0].getXYValue());
5760 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5761 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005762 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005763 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005764 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005765 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5766 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5767}
5768
chaviw09c8d2d2020-08-24 15:48:26 -07005769/**
5770 * Ensure that separate calls to sign the same data are generating the same key.
5771 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5772 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5773 * tests.
5774 */
5775TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5776 KeyEvent event = getTestKeyEvent();
5777 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5778
5779 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5780 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5781 ASSERT_EQ(hmac1, hmac2);
5782}
5783
5784/**
5785 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5786 */
5787TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5788 KeyEvent event = getTestKeyEvent();
5789 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5790 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5791
5792 verifiedEvent.deviceId += 1;
5793 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5794
5795 verifiedEvent.source += 1;
5796 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5797
5798 verifiedEvent.eventTimeNanos += 1;
5799 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5800
5801 verifiedEvent.displayId += 1;
5802 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5803
5804 verifiedEvent.action += 1;
5805 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5806
5807 verifiedEvent.downTimeNanos += 1;
5808 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5809
5810 verifiedEvent.flags += 1;
5811 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5812
5813 verifiedEvent.keyCode += 1;
5814 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5815
5816 verifiedEvent.scanCode += 1;
5817 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5818
5819 verifiedEvent.metaState += 1;
5820 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5821
5822 verifiedEvent.repeatCount += 1;
5823 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5824}
5825
Vishnu Nair958da932020-08-21 17:12:37 -07005826TEST_F(InputDispatcherTest, SetFocusedWindow) {
5827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5828 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005829 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005830 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005831 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005832 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5833
5834 // Top window is also focusable but is not granted focus.
5835 windowTop->setFocusable(true);
5836 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005837 mDispatcher->onWindowInfosChanged(
5838 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005839 setFocusedWindow(windowSecond);
5840
5841 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005843 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005844
5845 // Focused window should receive event.
5846 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5847 windowTop->assertNoEvents();
5848}
5849
5850TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5852 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005853 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005854 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5855
5856 window->setFocusable(true);
5857 // Release channel for window is no longer valid.
5858 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005859 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005860 setFocusedWindow(window);
5861
5862 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005863 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005864
5865 // window channel is invalid, so it should not receive any input event.
5866 window->assertNoEvents();
5867}
5868
5869TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5871 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005872 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005873 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005874 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5875
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005876 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005877 setFocusedWindow(window);
5878
5879 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005880 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005881
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005882 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005883 window->assertNoEvents();
5884}
5885
5886TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5888 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005889 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005890 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005891 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005892 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5893
5894 windowTop->setFocusable(true);
5895 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005896 mDispatcher->onWindowInfosChanged(
5897 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005898 setFocusedWindow(windowTop);
5899 windowTop->consumeFocusEvent(true);
5900
Chavi Weingarten847e8512023-03-29 00:26:09 +00005901 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005902 mDispatcher->onWindowInfosChanged(
5903 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005904 windowSecond->consumeFocusEvent(true);
5905 windowTop->consumeFocusEvent(false);
5906
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005908 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005909
5910 // Focused window should receive event.
5911 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5912}
5913
Chavi Weingarten847e8512023-03-29 00:26:09 +00005914TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5916 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005917 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005918 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005919 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005920 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5921
5922 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005923 windowSecond->setFocusable(false);
5924 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005925 mDispatcher->onWindowInfosChanged(
5926 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005927 setFocusedWindow(windowTop);
5928 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005929
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005931 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005932
5933 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005934 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005935 windowSecond->assertNoEvents();
5936}
5937
5938TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5940 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005941 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005942 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005943 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5944 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005945 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5946
5947 window->setFocusable(true);
5948 previousFocusedWindow->setFocusable(true);
5949 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005950 mDispatcher->onWindowInfosChanged(
5951 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005952 setFocusedWindow(previousFocusedWindow);
5953 previousFocusedWindow->consumeFocusEvent(true);
5954
5955 // Requesting focus on invisible window takes focus from currently focused window.
5956 setFocusedWindow(window);
5957 previousFocusedWindow->consumeFocusEvent(false);
5958
5959 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005961 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5962 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005963
5964 // Window does not get focus event or key down.
5965 window->assertNoEvents();
5966
5967 // Window becomes visible.
5968 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005969 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005970
5971 // Window receives focus event.
5972 window->consumeFocusEvent(true);
5973 // Focused window receives key down.
5974 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5975}
5976
Vishnu Nair599f1412021-06-21 10:39:58 -07005977TEST_F(InputDispatcherTest, DisplayRemoved) {
5978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5979 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005980 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005981 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5982
5983 // window is granted focus.
5984 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005985 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005986 setFocusedWindow(window);
5987 window->consumeFocusEvent(true);
5988
5989 // When a display is removed window loses focus.
5990 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5991 window->consumeFocusEvent(false);
5992}
5993
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005994/**
5995 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5996 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5997 * of the 'slipperyEnterWindow'.
5998 *
5999 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6000 * a way so that the touched location is no longer covered by the top window.
6001 *
6002 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6003 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6004 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6005 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6006 * with ACTION_DOWN).
6007 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6008 * window moved itself away from the touched location and had Flag::SLIPPERY.
6009 *
6010 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6011 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6012 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6013 *
6014 * In this test, we ensure that the event received by the bottom window has
6015 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6016 */
6017TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006018 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006019 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006020
6021 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6022 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6023
6024 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006025 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006026 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006027 // Make sure this one overlaps the bottom window
6028 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6029 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6030 // one. Windows with the same owner are not considered to be occluding each other.
6031 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6032
6033 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006034 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006035 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6036
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006037 mDispatcher->onWindowInfosChanged(
6038 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006039
6040 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006041 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6042 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6043 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006044 slipperyExitWindow->consumeMotionDown();
6045 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006046 mDispatcher->onWindowInfosChanged(
6047 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006048
Prabir Pradhan678438e2023-04-13 19:32:51 +00006049 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6050 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6051 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006052
6053 slipperyExitWindow->consumeMotionCancel();
6054
6055 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6056 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6057}
6058
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006059/**
6060 * Two windows, one on the left and another on the right. The left window is slippery. The right
6061 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6062 * touch moves from the left window into the right window, the gesture should continue to go to the
6063 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6064 * reproduces a crash.
6065 */
6066TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6067 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6068
6069 sp<FakeWindowHandle> leftSlipperyWindow =
6070 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6071 leftSlipperyWindow->setSlippery(true);
6072 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6073
6074 sp<FakeWindowHandle> rightDropTouchesWindow =
6075 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6076 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6077 rightDropTouchesWindow->setDropInput(true);
6078
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006079 mDispatcher->onWindowInfosChanged(
6080 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006081
6082 // Start touch in the left window
6083 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6084 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6085 .build());
6086 leftSlipperyWindow->consumeMotionDown();
6087
6088 // And move it into the right window
6089 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6090 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6091 .build());
6092
6093 // Since the right window isn't eligible to receive input, touch does not slip.
6094 // The left window continues to receive the gesture.
6095 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6096 rightDropTouchesWindow->assertNoEvents();
6097}
6098
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006099/**
6100 * A single window is on screen first. Touch is injected into that window. Next, a second window
6101 * appears. Since the first window is slippery, touch will move from the first window to the second.
6102 */
6103TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6105 sp<FakeWindowHandle> originalWindow =
6106 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6107 originalWindow->setFrame(Rect(0, 0, 200, 200));
6108 originalWindow->setSlippery(true);
6109
6110 sp<FakeWindowHandle> appearingWindow =
6111 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6112 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6113
6114 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6115
6116 // Touch down on the original window
6117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6118 injectMotionEvent(*mDispatcher,
6119 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6120 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6121 .build()));
6122 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6123
6124 // Now, a new window appears. This could be, for example, a notification shade that appears
6125 // after user starts to drag down on the launcher window.
6126 mDispatcher->onWindowInfosChanged(
6127 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6129 injectMotionEvent(*mDispatcher,
6130 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6131 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6132 .build()));
6133 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6134 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6136 injectMotionEvent(*mDispatcher,
6137 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6138 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6139 .build()));
6140 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6141
6142 originalWindow->assertNoEvents();
6143 appearingWindow->assertNoEvents();
6144}
6145
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006146TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006147 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6149
6150 sp<FakeWindowHandle> leftWindow =
6151 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6152 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006153 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006154
6155 sp<FakeWindowHandle> rightSpy =
6156 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6157 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006158 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006159 rightSpy->setSpy(true);
6160 rightSpy->setTrustedOverlay(true);
6161
6162 sp<FakeWindowHandle> rightWindow =
6163 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6164 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006165 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006166
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006167 mDispatcher->onWindowInfosChanged(
6168 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006169
6170 // Touch in the left window
6171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6172 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6173 .build());
6174 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6175 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006176 ASSERT_NO_FATAL_FAILURE(
6177 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006178
6179 // Touch another finger over the right windows
6180 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6181 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6182 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6183 .build());
6184 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6185 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6186 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6187 mDispatcher->waitForIdle();
6188 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006189 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6190 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006191
6192 // Release finger over left window. The UP actions are not treated as device interaction.
6193 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6194 // is part of the UP action, we do not treat this as device interaction.
6195 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6196 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6197 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6198 .build());
6199 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6200 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6201 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6202 mDispatcher->waitForIdle();
6203 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6204
6205 // Move remaining finger
6206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6207 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6208 .build());
6209 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6210 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6211 mDispatcher->waitForIdle();
6212 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006213 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006214
6215 // Release all fingers
6216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6217 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6218 .build());
6219 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6220 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6221 mDispatcher->waitForIdle();
6222 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6223}
6224
6225TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6227
6228 sp<FakeWindowHandle> window =
6229 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6230 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006231 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006232
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006233 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006234 setFocusedWindow(window);
6235 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6236
6237 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6238 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6239 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006240 ASSERT_NO_FATAL_FAILURE(
6241 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006242
6243 // The UP actions are not treated as device interaction.
6244 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6245 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6246 mDispatcher->waitForIdle();
6247 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6248}
6249
Garfield Tan1c7bc862020-01-28 13:24:04 -08006250class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6251protected:
6252 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6253 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6254
Chris Yea209fde2020-07-22 13:54:51 -07006255 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006256 sp<FakeWindowHandle> mWindow;
6257
6258 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006259 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006260 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006261 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006262 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006263 ASSERT_EQ(OK, mDispatcher->start());
6264
6265 setUpWindow();
6266 }
6267
6268 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006269 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006270 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006271
Vishnu Nair47074b82020-08-14 11:54:47 -07006272 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006273 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006274 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006275 mWindow->consumeFocusEvent(true);
6276 }
6277
Chris Ye2ad95392020-09-01 13:44:44 -07006278 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006279 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006280 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006281 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006282 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006283
6284 // Window should receive key down event.
6285 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6286 }
6287
6288 void expectKeyRepeatOnce(int32_t repeatCount) {
6289 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006290 mWindow->consumeKeyEvent(
6291 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006292 }
6293
Chris Ye2ad95392020-09-01 13:44:44 -07006294 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006295 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006296 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006297 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006298 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006299
6300 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006301 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006302 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006303 }
6304};
6305
6306TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006307 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006308 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6309 expectKeyRepeatOnce(repeatCount);
6310 }
6311}
6312
6313TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006314 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006315 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6316 expectKeyRepeatOnce(repeatCount);
6317 }
Harry Cutts33476232023-01-30 19:57:29 +00006318 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006319 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006320 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6321 expectKeyRepeatOnce(repeatCount);
6322 }
6323}
6324
6325TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006326 sendAndConsumeKeyDown(/*deviceId=*/1);
6327 expectKeyRepeatOnce(/*repeatCount=*/1);
6328 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006329 mWindow->assertNoEvents();
6330}
6331
6332TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006333 sendAndConsumeKeyDown(/*deviceId=*/1);
6334 expectKeyRepeatOnce(/*repeatCount=*/1);
6335 sendAndConsumeKeyDown(/*deviceId=*/2);
6336 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006337 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006338 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006339 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006340 expectKeyRepeatOnce(/*repeatCount=*/2);
6341 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006342 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006343 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006344 mWindow->assertNoEvents();
6345}
6346
6347TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006348 sendAndConsumeKeyDown(/*deviceId=*/1);
6349 expectKeyRepeatOnce(/*repeatCount=*/1);
6350 sendAndConsumeKeyDown(/*deviceId=*/2);
6351 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006352 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006353 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006354 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006355 mWindow->assertNoEvents();
6356}
6357
liushenxiang42232912021-05-21 20:24:09 +08006358TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6359 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006360 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006361 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006362 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6363 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6364 mWindow->assertNoEvents();
6365}
6366
Garfield Tan1c7bc862020-01-28 13:24:04 -08006367TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006368 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006369 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006370 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006371 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006372 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6373 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6374 IdGenerator::getSource(repeatEvent->getId()));
6375 }
6376}
6377
6378TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006379 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006380 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006381
6382 std::unordered_set<int32_t> idSet;
6383 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006384 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006385 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6386 int32_t id = repeatEvent->getId();
6387 EXPECT_EQ(idSet.end(), idSet.find(id));
6388 idSet.insert(id);
6389 }
6390}
6391
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006392/* Test InputDispatcher for MultiDisplay */
6393class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6394public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006395 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006396 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006397
Chris Yea209fde2020-07-22 13:54:51 -07006398 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006399 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006400 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006401
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006402 // Set focus window for primary display, but focused display would be second one.
6403 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006404 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006405 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6406
Vishnu Nair958da932020-08-21 17:12:37 -07006407 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006408 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006409
Chris Yea209fde2020-07-22 13:54:51 -07006410 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006411 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006412 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006413 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006414 // Set focus display to second one.
6415 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6416 // Set focus window for second display.
6417 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006418 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006419 mDispatcher->onWindowInfosChanged(
6420 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006421 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006422 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006423 }
6424
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006425 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006426 InputDispatcherTest::TearDown();
6427
Chris Yea209fde2020-07-22 13:54:51 -07006428 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006429 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006430 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006431 windowInSecondary.clear();
6432 }
6433
6434protected:
Chris Yea209fde2020-07-22 13:54:51 -07006435 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006436 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006437 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006438 sp<FakeWindowHandle> windowInSecondary;
6439};
6440
6441TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6442 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006444 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006446 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006447 windowInSecondary->assertNoEvents();
6448
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006449 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006451 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006453 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006454 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006455}
6456
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006457TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006458 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006460 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006461 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006462 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006463 windowInSecondary->assertNoEvents();
6464
6465 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006467 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006468 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006469 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006470
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006471 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006472 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006473
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006474 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006475 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006476 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006477
6478 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006479 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006480 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006481 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006482 windowInSecondary->assertNoEvents();
6483}
6484
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006485// Test per-display input monitors for motion event.
6486TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006487 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006488 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006489 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006490 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006491
6492 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006494 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006496 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006497 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006498 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006499 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006500
6501 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006503 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006505 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006506 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006507 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006508 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006509
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006510 // Lift up the touch from the second display
6511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006512 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6514 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6515 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6516
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006517 // Test inject a non-pointer motion event.
6518 // If specific a display, it will dispatch to the focused window of particular display,
6519 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006521 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006523 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006524 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006525 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006526 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006527}
6528
6529// Test per-display input monitors for key event.
6530TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006531 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006532 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006533 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006534 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006535 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006536
6537 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006539 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006540 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006541 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006542 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006543 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006544}
6545
Vishnu Nair958da932020-08-21 17:12:37 -07006546TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6547 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006548 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006549 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006550 mDispatcher->onWindowInfosChanged(
6551 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6552 *windowInSecondary->getInfo()},
6553 {},
6554 0,
6555 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006556 setFocusedWindow(secondWindowInPrimary);
6557 windowInPrimary->consumeFocusEvent(false);
6558 secondWindowInPrimary->consumeFocusEvent(true);
6559
6560 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6562 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006563 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006564 windowInPrimary->assertNoEvents();
6565 windowInSecondary->assertNoEvents();
6566 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6567}
6568
Arthur Hungdfd528e2021-12-08 13:23:04 +00006569TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6570 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006571 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006572 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006573 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006574
6575 // Test touch down on primary display.
6576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006577 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6579 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6580 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6581
6582 // Test touch down on second display.
6583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006584 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6586 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6587 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6588
6589 // Trigger cancel touch.
6590 mDispatcher->cancelCurrentTouch();
6591 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6592 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6593 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6594 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6595
6596 // Test inject a move motion event, no window/monitor should receive the event.
6597 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006598 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006599 ADISPLAY_ID_DEFAULT, {110, 200}))
6600 << "Inject motion event should return InputEventInjectionResult::FAILED";
6601 windowInPrimary->assertNoEvents();
6602 monitorInPrimary.assertNoEvents();
6603
6604 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006605 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006606 SECOND_DISPLAY_ID, {110, 200}))
6607 << "Inject motion event should return InputEventInjectionResult::FAILED";
6608 windowInSecondary->assertNoEvents();
6609 monitorInSecondary.assertNoEvents();
6610}
6611
Jackal Guof9696682018-10-05 12:23:23 +08006612class InputFilterTest : public InputDispatcherTest {
6613protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006614 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6615 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006616 NotifyMotionArgs motionArgs;
6617
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006618 motionArgs =
6619 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006620 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006621 motionArgs =
6622 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006623 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006624 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006625 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006626 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006627 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006628 } else {
6629 mFakePolicy->assertFilterInputEventWasNotCalled();
6630 }
6631 }
6632
6633 void testNotifyKey(bool expectToBeFiltered) {
6634 NotifyKeyArgs keyArgs;
6635
6636 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006637 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006638 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006639 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006640 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006641
6642 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006643 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006644 } else {
6645 mFakePolicy->assertFilterInputEventWasNotCalled();
6646 }
6647 }
6648};
6649
6650// Test InputFilter for MotionEvent
6651TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6652 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006653 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6654 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006655
6656 // Enable InputFilter
6657 mDispatcher->setInputFilterEnabled(true);
6658 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006659 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6660 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006661
6662 // Disable InputFilter
6663 mDispatcher->setInputFilterEnabled(false);
6664 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006665 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6666 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006667}
6668
6669// Test InputFilter for KeyEvent
6670TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6671 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006672 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006673
6674 // Enable InputFilter
6675 mDispatcher->setInputFilterEnabled(true);
6676 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006677 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006678
6679 // Disable InputFilter
6680 mDispatcher->setInputFilterEnabled(false);
6681 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006682 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006683}
6684
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006685// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6686// logical display coordinate space.
6687TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6688 ui::Transform firstDisplayTransform;
6689 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6690 ui::Transform secondDisplayTransform;
6691 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6692
6693 std::vector<gui::DisplayInfo> displayInfos(2);
6694 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6695 displayInfos[0].transform = firstDisplayTransform;
6696 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6697 displayInfos[1].transform = secondDisplayTransform;
6698
Patrick Williamsd828f302023-04-28 17:52:08 -05006699 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006700
6701 // Enable InputFilter
6702 mDispatcher->setInputFilterEnabled(true);
6703
6704 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006705 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6706 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006707}
6708
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006709class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6710protected:
6711 virtual void SetUp() override {
6712 InputDispatcherTest::SetUp();
6713
6714 /**
6715 * We don't need to enable input filter to test the injected event policy, but we enabled it
6716 * here to make the tests more realistic, since this policy only matters when inputfilter is
6717 * on.
6718 */
6719 mDispatcher->setInputFilterEnabled(true);
6720
6721 std::shared_ptr<InputApplicationHandle> application =
6722 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006723 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6724 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006725
6726 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6727 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006728 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006729 setFocusedWindow(mWindow);
6730 mWindow->consumeFocusEvent(true);
6731 }
6732
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006733 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6734 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006735 KeyEvent event;
6736
6737 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6738 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6739 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006740 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006741 const int32_t additionalPolicyFlags =
6742 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006744 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006745 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006746 policyFlags | additionalPolicyFlags));
6747
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006748 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006749 }
6750
6751 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6752 int32_t flags) {
6753 MotionEvent event;
6754 PointerProperties pointerProperties[1];
6755 PointerCoords pointerCoords[1];
6756 pointerProperties[0].clear();
6757 pointerProperties[0].id = 0;
6758 pointerCoords[0].clear();
6759 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6760 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6761
6762 ui::Transform identityTransform;
6763 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6764 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6765 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6766 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6767 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006768 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006769 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006770 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006771
6772 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006775 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006776 policyFlags | additionalPolicyFlags));
6777
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006778 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006779 }
6780
6781private:
6782 sp<FakeWindowHandle> mWindow;
6783};
6784
6785TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006786 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6787 // filter. Without it, the event will no different from a regularly injected event, and the
6788 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006789 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6790 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006791}
6792
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006793TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006794 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006795 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006796 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6797}
6798
6799TEST_F(InputFilterInjectionPolicyTest,
6800 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6801 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006802 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006803 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006804}
6805
6806TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006807 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6808 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006809}
6810
chaviwfd6d3512019-03-25 13:23:49 -07006811class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006812 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006813 InputDispatcherTest::SetUp();
6814
Chris Yea209fde2020-07-22 13:54:51 -07006815 std::shared_ptr<FakeApplicationHandle> application =
6816 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006817 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006818 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006819 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006820
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006821 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006822 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006823 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006824
6825 // Set focused application.
6826 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006827 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006828
6829 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006830 mDispatcher->onWindowInfosChanged(
6831 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006832 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006833 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006834 }
6835
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006836 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006837 InputDispatcherTest::TearDown();
6838
6839 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006840 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006841 }
6842
6843protected:
6844 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006845 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006846 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006847};
6848
6849// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6850// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6851// the onPointerDownOutsideFocus callback.
6852TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006854 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006855 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006857 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006858
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006859 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006860 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6861}
6862
6863// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6864// DOWN on the window that doesn't have focus. Ensure no window received the
6865// onPointerDownOutsideFocus callback.
6866TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006868 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6869 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006871 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006872
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006873 ASSERT_TRUE(mDispatcher->waitForIdle());
6874 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006875}
6876
6877// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6878// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6879TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006881 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006882 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006883 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006884
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006885 ASSERT_TRUE(mDispatcher->waitForIdle());
6886 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006887}
6888
6889// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6890// DOWN on the window that already has focus. Ensure no window received the
6891// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006892TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006894 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006895 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006897 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006898
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006899 ASSERT_TRUE(mDispatcher->waitForIdle());
6900 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006901}
6902
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006903// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6904// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6905TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6906 const MotionEvent event =
6907 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6908 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006909 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006910 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6911 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6914 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6915
6916 ASSERT_TRUE(mDispatcher->waitForIdle());
6917 mFakePolicy->assertOnPointerDownWasNotCalled();
6918 // Ensure that the unfocused window did not receive any FOCUS events.
6919 mUnfocusedWindow->assertNoEvents();
6920}
6921
chaviwaf87b3e2019-10-01 16:59:28 -07006922// These tests ensures we can send touch events to a single client when there are multiple input
6923// windows that point to the same client token.
6924class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6925 virtual void SetUp() override {
6926 InputDispatcherTest::SetUp();
6927
Chris Yea209fde2020-07-22 13:54:51 -07006928 std::shared_ptr<FakeApplicationHandle> application =
6929 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006930 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6931 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006932 mWindow1->setFrame(Rect(0, 0, 100, 100));
6933
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006934 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6935 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006936 mWindow2->setFrame(Rect(100, 100, 200, 200));
6937
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006938 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006939 }
6940
6941protected:
6942 sp<FakeWindowHandle> mWindow1;
6943 sp<FakeWindowHandle> mWindow2;
6944
6945 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006946 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006947 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6948 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006949 }
6950
6951 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6952 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006953 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006954 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006955
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006956 ASSERT_NE(nullptr, motionEvent)
6957 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006958
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006959 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006960 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006961
6962 for (size_t i = 0; i < points.size(); i++) {
6963 float expectedX = points[i].x;
6964 float expectedY = points[i].y;
6965
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006966 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006967 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006968 << ", got " << motionEvent->getX(i);
6969 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006970 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006971 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006972 }
6973 }
chaviw9eaa22c2020-07-01 16:21:27 -07006974
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006975 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006976 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006977 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6978 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006979
6980 // Always consume from window1 since it's the window that has the InputReceiver
6981 consumeMotionEvent(mWindow1, action, expectedPoints);
6982 }
chaviwaf87b3e2019-10-01 16:59:28 -07006983};
6984
6985TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6986 // Touch Window 1
6987 PointF touchedPoint = {10, 10};
6988 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006989 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006990
6991 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006992 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006993
6994 // Touch Window 2
6995 touchedPoint = {150, 150};
6996 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006997 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006998}
6999
chaviw9eaa22c2020-07-01 16:21:27 -07007000TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7001 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007002 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007003 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007004
7005 // Touch Window 1
7006 PointF touchedPoint = {10, 10};
7007 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007008 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007009 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007010 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007011
7012 // Touch Window 2
7013 touchedPoint = {150, 150};
7014 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007015 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7016 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007017
chaviw9eaa22c2020-07-01 16:21:27 -07007018 // Update the transform so rotation is set
7019 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007020 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007021 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7022 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007023}
7024
chaviw9eaa22c2020-07-01 16:21:27 -07007025TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007026 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007027 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007028
7029 // Touch Window 1
7030 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7031 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007032 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007033
7034 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007035 touchedPoints.push_back(PointF{150, 150});
7036 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007037 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007038
chaviw9eaa22c2020-07-01 16:21:27 -07007039 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007040 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007041 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007042
chaviw9eaa22c2020-07-01 16:21:27 -07007043 // Update the transform so rotation is set for Window 2
7044 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007045 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007046 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007047 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007048}
7049
chaviw9eaa22c2020-07-01 16:21:27 -07007050TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007051 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007052 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007053
7054 // Touch Window 1
7055 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7056 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007057 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007058
7059 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007060 touchedPoints.push_back(PointF{150, 150});
7061 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007062
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007063 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007064
7065 // Move both windows
7066 touchedPoints = {{20, 20}, {175, 175}};
7067 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7068 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7069
chaviw9eaa22c2020-07-01 16:21:27 -07007070 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007071
chaviw9eaa22c2020-07-01 16:21:27 -07007072 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007073 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007074 expectedPoints.pop_back();
7075
7076 // Touch Window 2
7077 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007078 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007079 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007080 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007081
7082 // Move both windows
7083 touchedPoints = {{20, 20}, {175, 175}};
7084 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7085 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7086
7087 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007088}
7089
7090TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7091 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007092 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007093
7094 // Touch Window 1
7095 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7096 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007097 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007098
7099 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007100 touchedPoints.push_back(PointF{150, 150});
7101 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007102
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007103 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007104
7105 // Move both windows
7106 touchedPoints = {{20, 20}, {175, 175}};
7107 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7108 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7109
chaviw9eaa22c2020-07-01 16:21:27 -07007110 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007111}
7112
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007113/**
7114 * When one of the windows is slippery, the touch should not slip into the other window with the
7115 * same input channel.
7116 */
7117TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7118 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007119 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007120
7121 // Touch down in window 1
7122 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7123 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7124 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7125
7126 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7127 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7128 // getting generated.
7129 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7130 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7131
7132 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7133}
7134
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007135/**
7136 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7137 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7138 * that the pointer is hovering over may have a different transform.
7139 */
7140TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007141 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007142
7143 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7145 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7146 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007147 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7148 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007149 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007150 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7151 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7152 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007153 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7154 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7155 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7156}
7157
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007158class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7159 virtual void SetUp() override {
7160 InputDispatcherTest::SetUp();
7161
Chris Yea209fde2020-07-22 13:54:51 -07007162 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007163 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007164 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7165 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007166 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007167 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007168 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007169
7170 // Set focused application.
7171 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7172
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007173 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007174 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007175 mWindow->consumeFocusEvent(true);
7176 }
7177
7178 virtual void TearDown() override {
7179 InputDispatcherTest::TearDown();
7180 mWindow.clear();
7181 }
7182
7183protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007184 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007185 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007186 sp<FakeWindowHandle> mWindow;
7187 static constexpr PointF WINDOW_LOCATION = {20, 20};
7188
7189 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007191 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007192 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007194 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007195 WINDOW_LOCATION));
7196 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007197
7198 sp<FakeWindowHandle> addSpyWindow() {
7199 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007200 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007201 spy->setTrustedOverlay(true);
7202 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007203 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007204 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007205 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007206 return spy;
7207 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007208};
7209
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007210// Send a tap and respond, which should not cause an ANR.
7211TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7212 tapOnWindow();
7213 mWindow->consumeMotionDown();
7214 mWindow->consumeMotionUp();
7215 ASSERT_TRUE(mDispatcher->waitForIdle());
7216 mFakePolicy->assertNotifyAnrWasNotCalled();
7217}
7218
7219// Send a regular key and respond, which should not cause an ANR.
7220TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007222 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7223 ASSERT_TRUE(mDispatcher->waitForIdle());
7224 mFakePolicy->assertNotifyAnrWasNotCalled();
7225}
7226
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007227TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7228 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007229 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007230 mWindow->consumeFocusEvent(false);
7231
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007232 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007233 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7234 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007235 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007237 // Key will not go to window because we have no focused window.
7238 // The 'no focused window' ANR timer should start instead.
7239
7240 // Now, the focused application goes away.
7241 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7242 // The key should get dropped and there should be no ANR.
7243
7244 ASSERT_TRUE(mDispatcher->waitForIdle());
7245 mFakePolicy->assertNotifyAnrWasNotCalled();
7246}
7247
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007248// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007249// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7250// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007251TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007253 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007254 WINDOW_LOCATION));
7255
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007256 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7257 ASSERT_TRUE(sequenceNum);
7258 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007259 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007260
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007261 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007262 mWindow->consumeMotionEvent(
7263 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007264 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007265 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007266}
7267
7268// Send a key to the app and have the app not respond right away.
7269TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7270 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007272 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7273 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007274 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007275 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007276 ASSERT_TRUE(mDispatcher->waitForIdle());
7277}
7278
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279// We have a focused application, but no focused window
7280TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007281 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007282 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007283 mWindow->consumeFocusEvent(false);
7284
7285 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007287 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007288 WINDOW_LOCATION));
7289 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7290 mDispatcher->waitForIdle();
7291 mFakePolicy->assertNotifyAnrWasNotCalled();
7292
7293 // Once a focused event arrives, we get an ANR for this application
7294 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7295 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007296 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007297 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007298 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007299 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007300 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007301 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007302 ASSERT_TRUE(mDispatcher->waitForIdle());
7303}
7304
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007305/**
7306 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7307 * there will not be an ANR.
7308 */
7309TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7310 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007311 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007312 mWindow->consumeFocusEvent(false);
7313
7314 KeyEvent event;
7315 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7316 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7317
7318 // Define a valid key down event that is stale (too old).
7319 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007320 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007321 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007322
7323 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7324
7325 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007326 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007327 InputEventInjectionSync::WAIT_FOR_RESULT,
7328 INJECT_EVENT_TIMEOUT, policyFlags);
7329 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7330 << "Injection should fail because the event is stale";
7331
7332 ASSERT_TRUE(mDispatcher->waitForIdle());
7333 mFakePolicy->assertNotifyAnrWasNotCalled();
7334 mWindow->assertNoEvents();
7335}
7336
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007337// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007338// Make sure that we don't notify policy twice about the same ANR.
7339TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007340 const std::chrono::duration appTimeout = 400ms;
7341 mApplication->setDispatchingTimeout(appTimeout);
7342 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7343
Vishnu Nair47074b82020-08-14 11:54:47 -07007344 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007345 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007346 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007347
7348 // Once a focused event arrives, we get an ANR for this application
7349 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7350 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007351 const std::chrono::duration eventInjectionTimeout = 100ms;
7352 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007353 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007354 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007355 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7356 /*allowKeyRepeat=*/false);
7357 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7358 << "result=" << ftl::enum_string(result);
7359 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7360 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7361 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7362 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007363
Vishnu Naire4df8752022-09-08 09:17:55 -07007364 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007365 // ANR should not be raised again. It is up to policy to do that if it desires.
7366 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007367
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007368 // If we now get a focused window, the ANR should stop, but the policy handles that via
7369 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007370 ASSERT_TRUE(mDispatcher->waitForIdle());
7371}
7372
7373// We have a focused application, but no focused window
7374TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007375 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007376 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377 mWindow->consumeFocusEvent(false);
7378
7379 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007380 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007381
Vishnu Naire4df8752022-09-08 09:17:55 -07007382 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7383 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007384
7385 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007386 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007387 ASSERT_TRUE(mDispatcher->waitForIdle());
7388 mWindow->assertNoEvents();
7389}
7390
7391/**
7392 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7393 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7394 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7395 * the ANR mechanism should still work.
7396 *
7397 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7398 * DOWN event, while not responding on the second one.
7399 */
7400TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7401 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007402 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007403 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7404 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7405 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007406 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007407
7408 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007409 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007410 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7411 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7412 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007413 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007414
7415 // We have now sent down and up. Let's consume first event and then ANR on the second.
7416 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7417 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007418 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007419}
7420
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007421// A spy window can receive an ANR
7422TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7423 sp<FakeWindowHandle> spy = addSpyWindow();
7424
7425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007426 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007427 WINDOW_LOCATION));
7428 mWindow->consumeMotionDown();
7429
7430 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7431 ASSERT_TRUE(sequenceNum);
7432 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007433 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007434
7435 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007436 spy->consumeMotionEvent(
7437 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007438 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007439 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007440}
7441
7442// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007443// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007444TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7445 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007446
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007448 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007449 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007451
7452 // Stuck on the ACTION_UP
7453 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007454 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007455
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007456 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007457 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007458 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7459 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007460
7461 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7462 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007463 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007464 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007465 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007466}
7467
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007468// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007469// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007470TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7471 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007472
7473 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007474 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7475 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007476
7477 mWindow->consumeMotionDown();
7478 // Stuck on the ACTION_UP
7479 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007480 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007481
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007482 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007483 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007484 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7485 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007486
7487 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7488 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007489 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007490 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007491 spy->assertNoEvents();
7492}
7493
7494TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007495 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007496
Prabir Pradhanfb549072023-10-05 19:17:36 +00007497 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007498
7499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007500 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007501 WINDOW_LOCATION));
7502
7503 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7504 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7505 ASSERT_TRUE(consumeSeq);
7506
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007507 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7508 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007509
7510 monitor.finishEvent(*consumeSeq);
7511 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7512
7513 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007514 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007515}
7516
7517// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7518// process events, you don't get an anr. When the window later becomes unresponsive again, you
7519// get an ANR again.
7520// 1. tap -> block on ACTION_UP -> receive ANR
7521// 2. consume all pending events (= queue becomes healthy again)
7522// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7523TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7524 tapOnWindow();
7525
7526 mWindow->consumeMotionDown();
7527 // Block on ACTION_UP
7528 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007529 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007530 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7531 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007532 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007533 mWindow->assertNoEvents();
7534
7535 tapOnWindow();
7536 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007537 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007538 mWindow->consumeMotionUp();
7539
7540 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007541 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007542 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007543 mWindow->assertNoEvents();
7544}
7545
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007546// If a connection remains unresponsive for a while, make sure policy is only notified once about
7547// it.
7548TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007550 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007551 WINDOW_LOCATION));
7552
7553 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007554 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007555 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007556 // 'notifyConnectionUnresponsive' should only be called once per connection
7557 mFakePolicy->assertNotifyAnrWasNotCalled();
7558 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007559 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007560 mWindow->consumeMotionEvent(
7561 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007562 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007563 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007564 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007565 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007566}
7567
7568/**
7569 * 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 -07007570 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007571 *
7572 * Warning!!!
7573 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7574 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007575 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007576 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7577 *
7578 * If that value changes, this test should also change.
7579 */
7580TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7581 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007582 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007583
7584 tapOnWindow();
7585 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7586 ASSERT_TRUE(downSequenceNum);
7587 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7588 ASSERT_TRUE(upSequenceNum);
7589 // Don't finish the events yet, and send a key
7590 // Injection will "succeed" because we will eventually give up and send the key to the focused
7591 // window even if motions are still being processed. But because the injection timeout is short,
7592 // we will receive INJECTION_TIMED_OUT as the result.
7593
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007594 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007595 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7596 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007597 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007598 // Key will not be sent to the window, yet, because the window is still processing events
7599 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007600 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7601 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7602 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7603 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007604
7605 std::this_thread::sleep_for(500ms);
7606 // if we wait long enough though, dispatcher will give up, and still send the key
7607 // to the focused window, even though we have not yet finished the motion event
7608 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7609 mWindow->finishEvent(*downSequenceNum);
7610 mWindow->finishEvent(*upSequenceNum);
7611}
7612
7613/**
7614 * If a window is processing a motion event, and then a key event comes in, the key event should
7615 * not go to the focused window until the motion is processed.
7616 * If then a new motion comes in, then the pending key event should be going to the currently
7617 * focused window right away.
7618 */
7619TEST_F(InputDispatcherSingleWindowAnr,
7620 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7621 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007622 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007623
7624 tapOnWindow();
7625 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7626 ASSERT_TRUE(downSequenceNum);
7627 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7628 ASSERT_TRUE(upSequenceNum);
7629 // Don't finish the events yet, and send a key
7630 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007632 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7633 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007634 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007635 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7636 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7637 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7638 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007639
7640 // Now tap down again. It should cause the pending key to go to the focused window right away.
7641 tapOnWindow();
7642 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7643 // the other events yet. We can finish events in any order.
7644 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7645 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7646 mWindow->consumeMotionDown();
7647 mWindow->consumeMotionUp();
7648 mWindow->assertNoEvents();
7649}
7650
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007651/**
7652 * Send an event to the app and have the app not respond right away.
7653 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7654 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7655 * At some point, the window becomes responsive again.
7656 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7657 */
7658TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7659 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7660 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7661 .build());
7662
7663 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7664 ASSERT_TRUE(sequenceNum);
7665 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7666 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7667
7668 mWindow->finishEvent(*sequenceNum);
7669 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7670 ASSERT_TRUE(mDispatcher->waitForIdle());
7671 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7672
7673 // Now that the window is responsive, let's continue the gesture.
7674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7675 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7676 .build());
7677
7678 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7679 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7680 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7681 .build());
7682
7683 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7684 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7685 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7686 .build());
7687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7688 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7689 .build());
7690 // We already canceled this pointer, so the window shouldn't get any new events.
7691 mWindow->assertNoEvents();
7692
7693 // Start another one.
7694 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7695 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7696 .build());
7697 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7698}
7699
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007700class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7701 virtual void SetUp() override {
7702 InputDispatcherTest::SetUp();
7703
Chris Yea209fde2020-07-22 13:54:51 -07007704 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007705 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007706 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7707 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007708 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007709 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007710 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007711
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007712 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7713 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007714 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007715 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007716
7717 // Set focused application.
7718 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007719 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007720
7721 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007722 mDispatcher->onWindowInfosChanged(
7723 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007724 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007725 mFocusedWindow->consumeFocusEvent(true);
7726 }
7727
7728 virtual void TearDown() override {
7729 InputDispatcherTest::TearDown();
7730
7731 mUnfocusedWindow.clear();
7732 mFocusedWindow.clear();
7733 }
7734
7735protected:
Chris Yea209fde2020-07-22 13:54:51 -07007736 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007737 sp<FakeWindowHandle> mUnfocusedWindow;
7738 sp<FakeWindowHandle> mFocusedWindow;
7739 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7740 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7741 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7742
7743 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7744
7745 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7746
7747private:
7748 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007750 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007751 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007753 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007754 location));
7755 }
7756};
7757
7758// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7759// should be ANR'd first.
7760TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007762 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007763 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007765 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007766 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007767 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007768 // We consumed all events, so no ANR
7769 ASSERT_TRUE(mDispatcher->waitForIdle());
7770 mFakePolicy->assertNotifyAnrWasNotCalled();
7771
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007773 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007774 FOCUSED_WINDOW_LOCATION));
7775 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7776 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007777
7778 const std::chrono::duration timeout =
7779 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007780 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007781 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7782 // sequence to make it consistent
7783 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007785 mFocusedWindow->consumeMotionDown();
7786 // This cancel is generated because the connection was unresponsive
7787 mFocusedWindow->consumeMotionCancel();
7788 mFocusedWindow->assertNoEvents();
7789 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007790 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007791 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7792 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007793 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007794}
7795
7796// If we have 2 windows with identical timeouts that are both unresponsive,
7797// it doesn't matter which order they should have ANR.
7798// But we should receive ANR for both.
7799TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7800 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007801 mUnfocusedWindow->setDispatchingTimeout(
7802 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007803 mDispatcher->onWindowInfosChanged(
7804 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007805
7806 tapOnFocusedWindow();
7807 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007808 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007809 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7810 mFocusedWindow->getDispatchingTimeout(
7811 DISPATCHING_TIMEOUT)),
7812 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7813
7814 ASSERT_THAT(anrConnectionTokens,
7815 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7816 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007817
7818 ASSERT_TRUE(mDispatcher->waitForIdle());
7819 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007820
7821 mFocusedWindow->consumeMotionDown();
7822 mFocusedWindow->consumeMotionUp();
7823 mUnfocusedWindow->consumeMotionOutside();
7824
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007825 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7826 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007827
7828 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007829 ASSERT_THAT(responsiveTokens,
7830 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7831 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007832 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007833}
7834
7835// If a window is already not responding, the second tap on the same window should be ignored.
7836// We should also log an error to account for the dropped event (not tested here).
7837// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7838TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7839 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007840 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007841 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007842 // Receive the events, but don't respond
7843 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7844 ASSERT_TRUE(downEventSequenceNum);
7845 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7846 ASSERT_TRUE(upEventSequenceNum);
7847 const std::chrono::duration timeout =
7848 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007849 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007850
7851 // Tap once again
7852 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007853 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007854 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007855 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007856 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007857 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007858 FOCUSED_WINDOW_LOCATION));
7859 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7860 // valid touch target
7861 mUnfocusedWindow->assertNoEvents();
7862
7863 // Consume the first tap
7864 mFocusedWindow->finishEvent(*downEventSequenceNum);
7865 mFocusedWindow->finishEvent(*upEventSequenceNum);
7866 ASSERT_TRUE(mDispatcher->waitForIdle());
7867 // The second tap did not go to the focused window
7868 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007869 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007870 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7871 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007872 mFakePolicy->assertNotifyAnrWasNotCalled();
7873}
7874
7875// If you tap outside of all windows, there will not be ANR
7876TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007877 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007878 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007879 LOCATION_OUTSIDE_ALL_WINDOWS));
7880 ASSERT_TRUE(mDispatcher->waitForIdle());
7881 mFakePolicy->assertNotifyAnrWasNotCalled();
7882}
7883
7884// Since the focused window is paused, tapping on it should not produce any events
7885TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7886 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007887 mDispatcher->onWindowInfosChanged(
7888 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007889
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007890 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007891 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007892 FOCUSED_WINDOW_LOCATION));
7893
7894 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7895 ASSERT_TRUE(mDispatcher->waitForIdle());
7896 // Should not ANR because the window is paused, and touches shouldn't go to it
7897 mFakePolicy->assertNotifyAnrWasNotCalled();
7898
7899 mFocusedWindow->assertNoEvents();
7900 mUnfocusedWindow->assertNoEvents();
7901}
7902
7903/**
7904 * 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 -07007905 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007906 * If a different window becomes focused at this time, the key should go to that window instead.
7907 *
7908 * Warning!!!
7909 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7910 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007911 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007912 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7913 *
7914 * If that value changes, this test should also change.
7915 */
7916TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7917 // Set a long ANR timeout to prevent it from triggering
7918 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007919 mDispatcher->onWindowInfosChanged(
7920 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007921
7922 tapOnUnfocusedWindow();
7923 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7924 ASSERT_TRUE(downSequenceNum);
7925 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7926 ASSERT_TRUE(upSequenceNum);
7927 // Don't finish the events yet, and send a key
7928 // Injection will succeed because we will eventually give up and send the key to the focused
7929 // window even if motions are still being processed.
7930
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007931 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007932 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7933 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007935 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007936 // and the key remains pending, waiting for the touch events to be processed.
7937 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7938 // under the hood.
7939 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7940 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007941
7942 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007943 mFocusedWindow->setFocusable(false);
7944 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007945 mDispatcher->onWindowInfosChanged(
7946 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007947 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007948
7949 // Focus events should precede the key events
7950 mUnfocusedWindow->consumeFocusEvent(true);
7951 mFocusedWindow->consumeFocusEvent(false);
7952
7953 // Finish the tap events, which should unblock dispatcher
7954 mUnfocusedWindow->finishEvent(*downSequenceNum);
7955 mUnfocusedWindow->finishEvent(*upSequenceNum);
7956
7957 // Now that all queues are cleared and no backlog in the connections, the key event
7958 // can finally go to the newly focused "mUnfocusedWindow".
7959 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7960 mFocusedWindow->assertNoEvents();
7961 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007962 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007963}
7964
7965// When the touch stream is split across 2 windows, and one of them does not respond,
7966// then ANR should be raised and the touch should be canceled for the unresponsive window.
7967// The other window should not be affected by that.
7968TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7969 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007970 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7971 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7972 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007973 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007974 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007975
7976 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007977 mDispatcher->notifyMotion(
7978 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7979 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007980
7981 const std::chrono::duration timeout =
7982 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007983 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007984
7985 mUnfocusedWindow->consumeMotionDown();
7986 mFocusedWindow->consumeMotionDown();
7987 // Focused window may or may not receive ACTION_MOVE
7988 // But it should definitely receive ACTION_CANCEL due to the ANR
7989 InputEvent* event;
7990 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7991 ASSERT_TRUE(moveOrCancelSequenceNum);
7992 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7993 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007994 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007995 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7996 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7997 mFocusedWindow->consumeMotionCancel();
7998 } else {
7999 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8000 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008001 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008002 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8003 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008004
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008005 mUnfocusedWindow->assertNoEvents();
8006 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008007 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008008}
8009
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008010/**
8011 * If we have no focused window, and a key comes in, we start the ANR timer.
8012 * The focused application should add a focused window before the timer runs out to prevent ANR.
8013 *
8014 * If the user touches another application during this time, the key should be dropped.
8015 * Next, if a new focused window comes in, without toggling the focused application,
8016 * then no ANR should occur.
8017 *
8018 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8019 * but in some cases the policy may not update the focused application.
8020 */
8021TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8022 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8023 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008024 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008025 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8026 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8027 mFocusedWindow->setFocusable(false);
8028
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008029 mDispatcher->onWindowInfosChanged(
8030 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008031 mFocusedWindow->consumeFocusEvent(false);
8032
8033 // Send a key. The ANR timer should start because there is no focused window.
8034 // 'focusedApplication' will get blamed if this timer completes.
8035 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008036 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008037 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8038 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008039 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008041
8042 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8043 // then the injected touches won't cause the focused event to get dropped.
8044 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8045 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8046 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8047 // For this test, it means that the key would get delivered to the window once it becomes
8048 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008049 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008050
8051 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008052 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8053 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8054 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008055
8056 // We do not consume the motion right away, because that would require dispatcher to first
8057 // process (== drop) the key event, and by that time, ANR will be raised.
8058 // Set the focused window first.
8059 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008060 mDispatcher->onWindowInfosChanged(
8061 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008062 setFocusedWindow(mFocusedWindow);
8063 mFocusedWindow->consumeFocusEvent(true);
8064 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8065 // to another application. This could be a bug / behaviour in the policy.
8066
8067 mUnfocusedWindow->consumeMotionDown();
8068
8069 ASSERT_TRUE(mDispatcher->waitForIdle());
8070 // Should not ANR because we actually have a focused window. It was just added too slowly.
8071 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8072}
8073
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008074// These tests ensure we cannot send touch events to a window that's positioned behind a window
8075// that has feature NO_INPUT_CHANNEL.
8076// Layout:
8077// Top (closest to user)
8078// mNoInputWindow (above all windows)
8079// mBottomWindow
8080// Bottom (furthest from user)
8081class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8082 virtual void SetUp() override {
8083 InputDispatcherTest::SetUp();
8084
8085 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008086 mNoInputWindow =
8087 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8088 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008089 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008090 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008091 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8092 // It's perfectly valid for this window to not have an associated input channel
8093
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008094 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8095 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008096 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8097
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008098 mDispatcher->onWindowInfosChanged(
8099 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008100 }
8101
8102protected:
8103 std::shared_ptr<FakeApplicationHandle> mApplication;
8104 sp<FakeWindowHandle> mNoInputWindow;
8105 sp<FakeWindowHandle> mBottomWindow;
8106};
8107
8108TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8109 PointF touchedPoint = {10, 10};
8110
Prabir Pradhan678438e2023-04-13 19:32:51 +00008111 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8112 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8113 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008114
8115 mNoInputWindow->assertNoEvents();
8116 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8117 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8118 // and therefore should prevent mBottomWindow from receiving touches
8119 mBottomWindow->assertNoEvents();
8120}
8121
8122/**
8123 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8124 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8125 */
8126TEST_F(InputDispatcherMultiWindowOcclusionTests,
8127 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008128 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8129 "Window with input channel and NO_INPUT_CHANNEL",
8130 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008131
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008132 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008133 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008134 mDispatcher->onWindowInfosChanged(
8135 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008136
8137 PointF touchedPoint = {10, 10};
8138
Prabir Pradhan678438e2023-04-13 19:32:51 +00008139 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8140 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8141 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008142
8143 mNoInputWindow->assertNoEvents();
8144 mBottomWindow->assertNoEvents();
8145}
8146
Vishnu Nair958da932020-08-21 17:12:37 -07008147class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8148protected:
8149 std::shared_ptr<FakeApplicationHandle> mApp;
8150 sp<FakeWindowHandle> mWindow;
8151 sp<FakeWindowHandle> mMirror;
8152
8153 virtual void SetUp() override {
8154 InputDispatcherTest::SetUp();
8155 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008156 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8157 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8158 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008159 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8160 mWindow->setFocusable(true);
8161 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008162 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008163 }
8164};
8165
8166TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8167 // Request focus on a mirrored window
8168 setFocusedWindow(mMirror);
8169
8170 // window gets focused
8171 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008173 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008174 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8175}
8176
8177// A focused & mirrored window remains focused only if the window and its mirror are both
8178// focusable.
8179TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8180 setFocusedWindow(mMirror);
8181
8182 // window gets focused
8183 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008185 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008186 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008188 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008189 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8190
8191 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008192 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008193
8194 // window loses focus since one of the windows associated with the token in not focusable
8195 mWindow->consumeFocusEvent(false);
8196
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008197 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008198 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008199 mWindow->assertNoEvents();
8200}
8201
8202// A focused & mirrored window remains focused until the window and its mirror both become
8203// invisible.
8204TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8205 setFocusedWindow(mMirror);
8206
8207 // window gets focused
8208 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008210 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008211 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008213 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008214 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8215
8216 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008217 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008218
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008220 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008221 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008223 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008224 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8225
8226 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008227 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008228
8229 // window loses focus only after all windows associated with the token become invisible.
8230 mWindow->consumeFocusEvent(false);
8231
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008232 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008233 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008234 mWindow->assertNoEvents();
8235}
8236
8237// A focused & mirrored window remains focused until both windows are removed.
8238TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8239 setFocusedWindow(mMirror);
8240
8241 // window gets focused
8242 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008244 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008245 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008247 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008248 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8249
8250 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008251 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008252
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008254 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008255 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008257 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008258 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8259
8260 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008261 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008262 mWindow->consumeFocusEvent(false);
8263
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008264 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008265 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008266 mWindow->assertNoEvents();
8267}
8268
8269// Focus request can be pending until one window becomes visible.
8270TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8271 // Request focus on an invisible mirror.
8272 mWindow->setVisible(false);
8273 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008274 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008275 setFocusedWindow(mMirror);
8276
8277 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008279 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8280 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008281
8282 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008283 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008284
8285 // window gets focused
8286 mWindow->consumeFocusEvent(true);
8287 // window gets the pending key event
8288 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8289}
Prabir Pradhan99987712020-11-10 18:43:05 -08008290
8291class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8292protected:
8293 std::shared_ptr<FakeApplicationHandle> mApp;
8294 sp<FakeWindowHandle> mWindow;
8295 sp<FakeWindowHandle> mSecondWindow;
8296
8297 void SetUp() override {
8298 InputDispatcherTest::SetUp();
8299 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008300 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008301 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008302 mSecondWindow =
8303 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008304 mSecondWindow->setFocusable(true);
8305
8306 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008307 mDispatcher->onWindowInfosChanged(
8308 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008309
8310 setFocusedWindow(mWindow);
8311 mWindow->consumeFocusEvent(true);
8312 }
8313
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008314 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008315 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008316 }
8317
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008318 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8319 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008320 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008321 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8322 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008323 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008324 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008325 }
8326};
8327
8328TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8329 // Ensure that capture cannot be obtained for unfocused windows.
8330 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8331 mFakePolicy->assertSetPointerCaptureNotCalled();
8332 mSecondWindow->assertNoEvents();
8333
8334 // Ensure that capture can be enabled from the focus window.
8335 requestAndVerifyPointerCapture(mWindow, true);
8336
8337 // Ensure that capture cannot be disabled from a window that does not have capture.
8338 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8339 mFakePolicy->assertSetPointerCaptureNotCalled();
8340
8341 // Ensure that capture can be disabled from the window with capture.
8342 requestAndVerifyPointerCapture(mWindow, false);
8343}
8344
8345TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008346 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008347
8348 setFocusedWindow(mSecondWindow);
8349
8350 // Ensure that the capture disabled event was sent first.
8351 mWindow->consumeCaptureEvent(false);
8352 mWindow->consumeFocusEvent(false);
8353 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008354 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008355
8356 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008357 notifyPointerCaptureChanged({});
8358 notifyPointerCaptureChanged(request);
8359 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008360 mWindow->assertNoEvents();
8361 mSecondWindow->assertNoEvents();
8362 mFakePolicy->assertSetPointerCaptureNotCalled();
8363}
8364
8365TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008366 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008367
8368 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008369 notifyPointerCaptureChanged({});
8370 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008371
8372 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008373 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008374 mWindow->consumeCaptureEvent(false);
8375 mWindow->assertNoEvents();
8376}
8377
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008378TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8379 requestAndVerifyPointerCapture(mWindow, true);
8380
8381 // The first window loses focus.
8382 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008383 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008384 mWindow->consumeCaptureEvent(false);
8385
8386 // Request Pointer Capture from the second window before the notification from InputReader
8387 // arrives.
8388 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008389 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008390
8391 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008392 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008393
8394 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008395 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008396
8397 mSecondWindow->consumeFocusEvent(true);
8398 mSecondWindow->consumeCaptureEvent(true);
8399}
8400
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008401TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8402 // App repeatedly enables and disables capture.
8403 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8404 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8405 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8406 mFakePolicy->assertSetPointerCaptureCalled(false);
8407 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8408 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8409
8410 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8411 // first request is now stale, this should do nothing.
8412 notifyPointerCaptureChanged(firstRequest);
8413 mWindow->assertNoEvents();
8414
8415 // InputReader notifies that the second request was enabled.
8416 notifyPointerCaptureChanged(secondRequest);
8417 mWindow->consumeCaptureEvent(true);
8418}
8419
Prabir Pradhan7092e262022-05-03 16:51:09 +00008420TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8421 requestAndVerifyPointerCapture(mWindow, true);
8422
8423 // App toggles pointer capture off and on.
8424 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8425 mFakePolicy->assertSetPointerCaptureCalled(false);
8426
8427 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8428 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8429
8430 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8431 // preceding "disable" request.
8432 notifyPointerCaptureChanged(enableRequest);
8433
8434 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8435 // any notifications.
8436 mWindow->assertNoEvents();
8437}
8438
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008439/**
8440 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8441 * mouse movements don't affect the previous mouse hovering state.
8442 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8443 * HOVER_MOVE events).
8444 */
8445TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8446 // Mouse hover on the window
8447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8449 .build());
8450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8451 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8452 .build());
8453
8454 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8455 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8456
8457 // Start pointer capture
8458 requestAndVerifyPointerCapture(mWindow, true);
8459
8460 // Send some relative mouse movements and receive them in the window.
8461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8462 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8463 .build());
8464 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8465 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8466
8467 // Stop pointer capture
8468 requestAndVerifyPointerCapture(mWindow, false);
8469
8470 // Continue hovering on the window
8471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8472 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8473 .build());
8474 mWindow->consumeMotionEvent(
8475 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8476
8477 mWindow->assertNoEvents();
8478}
8479
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008480class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8481protected:
8482 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008483
8484 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8485 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8486
8487 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8488 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8489
8490 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8491 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8492 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8493 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8494 MAXIMUM_OBSCURING_OPACITY);
8495
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008496 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8497 static constexpr gui::Uid APP_B_UID{10002};
8498 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008499
8500 sp<FakeWindowHandle> mTouchWindow;
8501
8502 virtual void SetUp() override {
8503 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008504 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008505 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8506 }
8507
8508 virtual void TearDown() override {
8509 InputDispatcherTest::TearDown();
8510 mTouchWindow.clear();
8511 }
8512
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008513 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008514 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008515 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008516 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008517 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008518 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008519 return window;
8520 }
8521
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008522 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008523 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8524 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008525 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008526 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008527 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008528 return window;
8529 }
8530
8531 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008532 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8533 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8534 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008535 }
8536};
8537
8538TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008539 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008540 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008541 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008542
8543 touch();
8544
8545 mTouchWindow->assertNoEvents();
8546}
8547
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008548TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008549 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8550 const sp<FakeWindowHandle>& w =
8551 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008552 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008553
8554 touch();
8555
8556 mTouchWindow->assertNoEvents();
8557}
8558
8559TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008560 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8561 const sp<FakeWindowHandle>& w =
8562 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008563 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008564
8565 touch();
8566
8567 w->assertNoEvents();
8568}
8569
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008570TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008571 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008572 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008573
8574 touch();
8575
8576 mTouchWindow->consumeAnyMotionDown();
8577}
8578
8579TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008580 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008581 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008582 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008583 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008584
8585 touch({PointF{100, 100}});
8586
8587 mTouchWindow->consumeAnyMotionDown();
8588}
8589
8590TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008591 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008592 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008593 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008594
8595 touch();
8596
8597 mTouchWindow->consumeAnyMotionDown();
8598}
8599
8600TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8601 const sp<FakeWindowHandle>& w =
8602 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008603 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008604
8605 touch();
8606
8607 mTouchWindow->consumeAnyMotionDown();
8608}
8609
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008610TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8611 const sp<FakeWindowHandle>& w =
8612 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008613 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008614
8615 touch();
8616
8617 w->assertNoEvents();
8618}
8619
8620/**
8621 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8622 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8623 * window, the occluding window will still receive ACTION_OUTSIDE event.
8624 */
8625TEST_F(InputDispatcherUntrustedTouchesTest,
8626 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8627 const sp<FakeWindowHandle>& w =
8628 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008629 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008630 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008631
8632 touch();
8633
8634 w->consumeMotionOutside();
8635}
8636
8637TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8638 const sp<FakeWindowHandle>& w =
8639 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008640 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008641 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008642
8643 touch();
8644
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008645 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008646}
8647
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008648TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008649 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008650 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8651 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008652 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008653
8654 touch();
8655
8656 mTouchWindow->consumeAnyMotionDown();
8657}
8658
8659TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8660 const sp<FakeWindowHandle>& w =
8661 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8662 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008663 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008664
8665 touch();
8666
8667 mTouchWindow->consumeAnyMotionDown();
8668}
8669
8670TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008671 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008672 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8673 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008674 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008675
8676 touch();
8677
8678 mTouchWindow->assertNoEvents();
8679}
8680
8681TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8682 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8683 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008684 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8685 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008686 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008687 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8688 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008689 mDispatcher->onWindowInfosChanged(
8690 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008691
8692 touch();
8693
8694 mTouchWindow->assertNoEvents();
8695}
8696
8697TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8698 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8699 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008700 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8701 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008702 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008703 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8704 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008705 mDispatcher->onWindowInfosChanged(
8706 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008707
8708 touch();
8709
8710 mTouchWindow->consumeAnyMotionDown();
8711}
8712
8713TEST_F(InputDispatcherUntrustedTouchesTest,
8714 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8715 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008716 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8717 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008718 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008719 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8720 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008721 mDispatcher->onWindowInfosChanged(
8722 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008723
8724 touch();
8725
8726 mTouchWindow->consumeAnyMotionDown();
8727}
8728
8729TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8730 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008731 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8732 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008733 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008734 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8735 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008736 mDispatcher->onWindowInfosChanged(
8737 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008738
8739 touch();
8740
8741 mTouchWindow->assertNoEvents();
8742}
8743
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008744TEST_F(InputDispatcherUntrustedTouchesTest,
8745 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8746 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008747 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8748 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008749 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008750 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8751 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008752 mDispatcher->onWindowInfosChanged(
8753 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008754
8755 touch();
8756
8757 mTouchWindow->assertNoEvents();
8758}
8759
8760TEST_F(InputDispatcherUntrustedTouchesTest,
8761 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8762 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008763 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8764 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008765 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008766 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8767 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008768 mDispatcher->onWindowInfosChanged(
8769 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008770
8771 touch();
8772
8773 mTouchWindow->consumeAnyMotionDown();
8774}
8775
8776TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8777 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008778 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8779 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008780 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008781
8782 touch();
8783
8784 mTouchWindow->consumeAnyMotionDown();
8785}
8786
8787TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8788 const sp<FakeWindowHandle>& w =
8789 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008790 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008791
8792 touch();
8793
8794 mTouchWindow->consumeAnyMotionDown();
8795}
8796
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008797TEST_F(InputDispatcherUntrustedTouchesTest,
8798 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8799 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8800 const sp<FakeWindowHandle>& w =
8801 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008802 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008803
8804 touch();
8805
8806 mTouchWindow->assertNoEvents();
8807}
8808
8809TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8810 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8811 const sp<FakeWindowHandle>& w =
8812 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008813 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008814
8815 touch();
8816
8817 mTouchWindow->consumeAnyMotionDown();
8818}
8819
8820TEST_F(InputDispatcherUntrustedTouchesTest,
8821 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8822 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8823 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008824 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8825 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008826 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008827
8828 touch();
8829
8830 mTouchWindow->consumeAnyMotionDown();
8831}
8832
8833TEST_F(InputDispatcherUntrustedTouchesTest,
8834 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8835 const sp<FakeWindowHandle>& w1 =
8836 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8837 OPACITY_BELOW_THRESHOLD);
8838 const sp<FakeWindowHandle>& w2 =
8839 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8840 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008841 mDispatcher->onWindowInfosChanged(
8842 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008843
8844 touch();
8845
8846 mTouchWindow->assertNoEvents();
8847}
8848
8849/**
8850 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8851 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8852 * (which alone would result in allowing touches) does not affect the blocking behavior.
8853 */
8854TEST_F(InputDispatcherUntrustedTouchesTest,
8855 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8856 const sp<FakeWindowHandle>& wB =
8857 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8858 OPACITY_BELOW_THRESHOLD);
8859 const sp<FakeWindowHandle>& wC =
8860 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8861 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008862 mDispatcher->onWindowInfosChanged(
8863 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008864
8865 touch();
8866
8867 mTouchWindow->assertNoEvents();
8868}
8869
8870/**
8871 * This test is testing that a window from a different UID but with same application token doesn't
8872 * block the touch. Apps can share the application token for close UI collaboration for example.
8873 */
8874TEST_F(InputDispatcherUntrustedTouchesTest,
8875 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8876 const sp<FakeWindowHandle>& w =
8877 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8878 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008879 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008880
8881 touch();
8882
8883 mTouchWindow->consumeAnyMotionDown();
8884}
8885
arthurhungb89ccb02020-12-30 16:19:01 +08008886class InputDispatcherDragTests : public InputDispatcherTest {
8887protected:
8888 std::shared_ptr<FakeApplicationHandle> mApp;
8889 sp<FakeWindowHandle> mWindow;
8890 sp<FakeWindowHandle> mSecondWindow;
8891 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008892 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008893 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8894 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008895
8896 void SetUp() override {
8897 InputDispatcherTest::SetUp();
8898 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008899 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008900 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008901
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008902 mSecondWindow =
8903 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008904 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008905
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008906 mSpyWindow =
8907 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008908 mSpyWindow->setSpy(true);
8909 mSpyWindow->setTrustedOverlay(true);
8910 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8911
arthurhungb89ccb02020-12-30 16:19:01 +08008912 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008913 mDispatcher->onWindowInfosChanged(
8914 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8915 {},
8916 0,
8917 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008918 }
8919
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008920 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8921 switch (fromSource) {
8922 case AINPUT_SOURCE_TOUCHSCREEN:
8923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008924 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008925 ADISPLAY_ID_DEFAULT, {50, 50}))
8926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8927 break;
8928 case AINPUT_SOURCE_STYLUS:
8929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008930 injectMotionEvent(*mDispatcher,
8931 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8932 AINPUT_SOURCE_STYLUS)
8933 .buttonState(
8934 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8935 .pointer(PointerBuilder(0, ToolType::STYLUS)
8936 .x(50)
8937 .y(50))
8938 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008939 break;
8940 case AINPUT_SOURCE_MOUSE:
8941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008942 injectMotionEvent(*mDispatcher,
8943 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8944 AINPUT_SOURCE_MOUSE)
8945 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8946 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8947 ToolType::MOUSE)
8948 .x(50)
8949 .y(50))
8950 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008951 break;
8952 default:
8953 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8954 }
arthurhungb89ccb02020-12-30 16:19:01 +08008955
8956 // Window should receive motion event.
8957 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008958 // Spy window should also receive motion event
8959 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008960 }
8961
8962 // Start performing drag, we will create a drag window and transfer touch to it.
8963 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8964 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008965 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008966 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008967 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008968 }
arthurhungb89ccb02020-12-30 16:19:01 +08008969
8970 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008971 mDragWindow =
8972 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008973 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008974 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8975 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8976 {},
8977 0,
8978 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008979
8980 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008981 bool transferred =
8982 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008983 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008984 if (transferred) {
8985 mWindow->consumeMotionCancel();
8986 mDragWindow->consumeMotionDown();
8987 }
8988 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008989 }
8990};
8991
8992TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008993 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008994
8995 // Move on window.
8996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008997 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008998 ADISPLAY_ID_DEFAULT, {50, 50}))
8999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9000 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9001 mWindow->consumeDragEvent(false, 50, 50);
9002 mSecondWindow->assertNoEvents();
9003
9004 // Move to another window.
9005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009006 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009007 ADISPLAY_ID_DEFAULT, {150, 50}))
9008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9009 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9010 mWindow->consumeDragEvent(true, 150, 50);
9011 mSecondWindow->consumeDragEvent(false, 50, 50);
9012
9013 // Move back to original window.
9014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009015 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009016 ADISPLAY_ID_DEFAULT, {50, 50}))
9017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9018 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9019 mWindow->consumeDragEvent(false, 50, 50);
9020 mSecondWindow->consumeDragEvent(true, -50, 50);
9021
9022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009023 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9024 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9026 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9027 mWindow->assertNoEvents();
9028 mSecondWindow->assertNoEvents();
9029}
9030
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009031TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009032 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009033
9034 // No cancel event after drag start
9035 mSpyWindow->assertNoEvents();
9036
9037 const MotionEvent secondFingerDownEvent =
9038 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9039 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009040 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9041 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009042 .build();
9043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009044 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009045 InputEventInjectionSync::WAIT_FOR_RESULT))
9046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9047
9048 // Receives cancel for first pointer after next pointer down
9049 mSpyWindow->consumeMotionCancel();
9050 mSpyWindow->consumeMotionDown();
9051
9052 mSpyWindow->assertNoEvents();
9053}
9054
arthurhungf452d0b2021-01-06 00:19:52 +08009055TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009056 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009057
9058 // Move on window.
9059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009060 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009061 ADISPLAY_ID_DEFAULT, {50, 50}))
9062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9063 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9064 mWindow->consumeDragEvent(false, 50, 50);
9065 mSecondWindow->assertNoEvents();
9066
9067 // Move to another window.
9068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009069 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009070 ADISPLAY_ID_DEFAULT, {150, 50}))
9071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9072 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9073 mWindow->consumeDragEvent(true, 150, 50);
9074 mSecondWindow->consumeDragEvent(false, 50, 50);
9075
9076 // drop to another window.
9077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009078 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009079 {150, 50}))
9080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9081 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009082 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009083 mWindow->assertNoEvents();
9084 mSecondWindow->assertNoEvents();
9085}
9086
arthurhung6d4bed92021-03-17 11:59:33 +08009087TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009088 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009089
9090 // Move on window and keep button pressed.
9091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009092 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009093 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9094 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009095 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009096 .build()))
9097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9098 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9099 mWindow->consumeDragEvent(false, 50, 50);
9100 mSecondWindow->assertNoEvents();
9101
9102 // Move to another window and release button, expect to drop item.
9103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009104 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009105 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9106 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009107 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009108 .build()))
9109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9110 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9111 mWindow->assertNoEvents();
9112 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009113 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009114
9115 // nothing to the window.
9116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009117 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009118 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9119 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009120 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009121 .build()))
9122 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9123 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9124 mWindow->assertNoEvents();
9125 mSecondWindow->assertNoEvents();
9126}
9127
Arthur Hung54745652022-04-20 07:17:41 +00009128TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009129 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009130
9131 // Set second window invisible.
9132 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009133 mDispatcher->onWindowInfosChanged(
9134 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009135
9136 // Move on window.
9137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009138 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009139 ADISPLAY_ID_DEFAULT, {50, 50}))
9140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9141 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9142 mWindow->consumeDragEvent(false, 50, 50);
9143 mSecondWindow->assertNoEvents();
9144
9145 // Move to another window.
9146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009147 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009148 ADISPLAY_ID_DEFAULT, {150, 50}))
9149 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9150 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9151 mWindow->consumeDragEvent(true, 150, 50);
9152 mSecondWindow->assertNoEvents();
9153
9154 // drop to another window.
9155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009156 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009157 {150, 50}))
9158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9159 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009160 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009161 mWindow->assertNoEvents();
9162 mSecondWindow->assertNoEvents();
9163}
9164
Arthur Hung54745652022-04-20 07:17:41 +00009165TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009166 // Ensure window could track pointerIds if it didn't support split touch.
9167 mWindow->setPreventSplitting(true);
9168
Arthur Hung54745652022-04-20 07:17:41 +00009169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009170 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009171 {50, 50}))
9172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9173 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9174
9175 const MotionEvent secondFingerDownEvent =
9176 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9177 .displayId(ADISPLAY_ID_DEFAULT)
9178 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009179 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9180 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009181 .build();
9182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009183 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009184 InputEventInjectionSync::WAIT_FOR_RESULT))
9185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009186 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009187
9188 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009189 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009190}
9191
9192TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9193 // First down on second window.
9194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009195 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009196 {150, 50}))
9197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9198
9199 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9200
9201 // Second down on first window.
9202 const MotionEvent secondFingerDownEvent =
9203 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9204 .displayId(ADISPLAY_ID_DEFAULT)
9205 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009206 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9207 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009208 .build();
9209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009210 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009211 InputEventInjectionSync::WAIT_FOR_RESULT))
9212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9213 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9214
9215 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009216 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009217
9218 // Move on window.
9219 const MotionEvent secondFingerMoveEvent =
9220 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9221 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009222 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9223 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009224 .build();
9225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009226 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009227 InputEventInjectionSync::WAIT_FOR_RESULT));
9228 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9229 mWindow->consumeDragEvent(false, 50, 50);
9230 mSecondWindow->consumeMotionMove();
9231
9232 // Release the drag pointer should perform drop.
9233 const MotionEvent secondFingerUpEvent =
9234 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9235 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009236 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9237 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009238 .build();
9239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009240 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009241 InputEventInjectionSync::WAIT_FOR_RESULT));
9242 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009243 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009244 mWindow->assertNoEvents();
9245 mSecondWindow->consumeMotionMove();
9246}
9247
Arthur Hung3915c1f2022-05-31 07:17:17 +00009248TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009249 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009250
9251 // Update window of second display.
9252 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009253 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009254 mDispatcher->onWindowInfosChanged(
9255 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9256 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9257 {},
9258 0,
9259 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009260
9261 // Let second display has a touch state.
9262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009263 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009264 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9265 AINPUT_SOURCE_TOUCHSCREEN)
9266 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009267 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009268 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009269 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009270 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009271 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009272 mDispatcher->onWindowInfosChanged(
9273 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9274 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9275 {},
9276 0,
9277 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009278
9279 // Move on window.
9280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009281 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009282 ADISPLAY_ID_DEFAULT, {50, 50}))
9283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9284 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9285 mWindow->consumeDragEvent(false, 50, 50);
9286 mSecondWindow->assertNoEvents();
9287
9288 // Move to another window.
9289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009290 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009291 ADISPLAY_ID_DEFAULT, {150, 50}))
9292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9293 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9294 mWindow->consumeDragEvent(true, 150, 50);
9295 mSecondWindow->consumeDragEvent(false, 50, 50);
9296
9297 // drop to another window.
9298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009299 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009300 {150, 50}))
9301 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9302 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009303 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009304 mWindow->assertNoEvents();
9305 mSecondWindow->assertNoEvents();
9306}
9307
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009308TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9309 startDrag(true, AINPUT_SOURCE_MOUSE);
9310 // Move on window.
9311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009312 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009313 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9314 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009315 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009316 .x(50)
9317 .y(50))
9318 .build()))
9319 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9320 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9321 mWindow->consumeDragEvent(false, 50, 50);
9322 mSecondWindow->assertNoEvents();
9323
9324 // Move to another window.
9325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009326 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009327 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9328 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009329 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009330 .x(150)
9331 .y(50))
9332 .build()))
9333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9334 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9335 mWindow->consumeDragEvent(true, 150, 50);
9336 mSecondWindow->consumeDragEvent(false, 50, 50);
9337
9338 // drop to another window.
9339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009340 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009341 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9342 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009343 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009344 .x(150)
9345 .y(50))
9346 .build()))
9347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9348 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009349 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009350 mWindow->assertNoEvents();
9351 mSecondWindow->assertNoEvents();
9352}
9353
Linnan Li5af92f92023-07-14 14:36:22 +08009354/**
9355 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9356 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9357 */
9358TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9359 // Down on second window
9360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9362 {150, 50}))
9363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9364
9365 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9366 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9367
9368 // Down on first window
9369 const MotionEvent secondFingerDownEvent =
9370 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9371 .displayId(ADISPLAY_ID_DEFAULT)
9372 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9373 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9374 .build();
9375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9376 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9377 InputEventInjectionSync::WAIT_FOR_RESULT))
9378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9379 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9380 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9381 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9382
9383 // Start drag on first window
9384 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9385
9386 // Trigger cancel
9387 mDispatcher->cancelCurrentTouch();
9388 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9389 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9390 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9391
9392 ASSERT_TRUE(mDispatcher->waitForIdle());
9393 // The D&D finished with nullptr
9394 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9395
9396 // Remove drag window
9397 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9398
9399 // Inject a simple gesture, ensure dispatcher not crashed
9400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9401 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9402 PointF{50, 50}))
9403 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9404 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9405
9406 const MotionEvent moveEvent =
9407 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9408 .displayId(ADISPLAY_ID_DEFAULT)
9409 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9410 .build();
9411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9412 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9413 InputEventInjectionSync::WAIT_FOR_RESULT))
9414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9415 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9416
9417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9418 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9419 {50, 50}))
9420 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9421 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9422}
9423
Vishnu Nair062a8672021-09-03 16:07:44 -07009424class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9425
9426TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9429 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009430 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009431 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9432 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009433 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009434 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009435 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009436
9437 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009438 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009439 window->assertNoEvents();
9440
Prabir Pradhan678438e2023-04-13 19:32:51 +00009441 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9442 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9444 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009445 window->assertNoEvents();
9446
9447 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009448 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009449 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009450
Prabir Pradhan678438e2023-04-13 19:32:51 +00009451 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009452 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9453
Prabir Pradhan678438e2023-04-13 19:32:51 +00009454 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9455 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009456 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9457 window->assertNoEvents();
9458}
9459
9460TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9461 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9462 std::make_shared<FakeApplicationHandle>();
9463 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009464 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9465 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009466 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009467 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009468 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009470 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9471 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009472 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009473 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009474 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9475 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009476 mDispatcher->onWindowInfosChanged(
9477 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009478 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009479 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009480
9481 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009482 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009483 window->assertNoEvents();
9484
Prabir Pradhan678438e2023-04-13 19:32:51 +00009485 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9486 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009487 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9488 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009489 window->assertNoEvents();
9490
9491 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009492 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009493 mDispatcher->onWindowInfosChanged(
9494 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009495
Prabir Pradhan678438e2023-04-13 19:32:51 +00009496 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009497 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9498
Prabir Pradhan678438e2023-04-13 19:32:51 +00009499 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9500 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009501 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9502 window->assertNoEvents();
9503}
9504
9505TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9506 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9507 std::make_shared<FakeApplicationHandle>();
9508 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009509 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9510 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009511 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009512 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009513 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009515 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9516 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009517 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009518 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009519 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9520 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009521 mDispatcher->onWindowInfosChanged(
9522 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009523 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009524 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009525
9526 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009527 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009528 window->assertNoEvents();
9529
Prabir Pradhan678438e2023-04-13 19:32:51 +00009530 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9531 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009532 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9533 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009534 window->assertNoEvents();
9535
9536 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009537 mDispatcher->onWindowInfosChanged(
9538 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009539
Prabir Pradhan678438e2023-04-13 19:32:51 +00009540 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009541 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9542
Prabir Pradhan678438e2023-04-13 19:32:51 +00009543 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9544 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009545 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9546 window->assertNoEvents();
9547}
9548
Antonio Kantekf16f2832021-09-28 04:39:20 +00009549class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9550protected:
9551 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009552 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009553 sp<FakeWindowHandle> mWindow;
9554 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009555 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009556
9557 void SetUp() override {
9558 InputDispatcherTest::SetUp();
9559
9560 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009561 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009562 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009563 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009564 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009565 mSecondWindow =
9566 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009567 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009568 mThirdWindow =
9569 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9570 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9571 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009572
9573 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009574 mDispatcher->onWindowInfosChanged(
9575 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9576 {},
9577 0,
9578 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009579 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009580 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009581
Antonio Kantek15beb512022-06-13 22:35:41 +00009582 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009583 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009584 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009585 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9586 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009587 mThirdWindow->assertNoEvents();
9588 }
9589
9590 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9591 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009592 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009593 SECOND_DISPLAY_ID)) {
9594 mWindow->assertNoEvents();
9595 mSecondWindow->assertNoEvents();
9596 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009597 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009598 }
9599
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009600 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009601 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009602 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9603 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009604 mWindow->consumeTouchModeEvent(inTouchMode);
9605 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009606 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009607 }
9608};
9609
Antonio Kantek26defcf2022-02-08 01:12:27 +00009610TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009611 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009612 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9613 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009614 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009615}
9616
Antonio Kantek26defcf2022-02-08 01:12:27 +00009617TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9618 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009619 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009620 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009621 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009622 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009623 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009624 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009625 mWindow->assertNoEvents();
9626 mSecondWindow->assertNoEvents();
9627}
9628
9629TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9630 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009631 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009632 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009633 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009634 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009635 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009636}
9637
Antonio Kantekf16f2832021-09-28 04:39:20 +00009638TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009639 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009640 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9641 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009642 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009643 mWindow->assertNoEvents();
9644 mSecondWindow->assertNoEvents();
9645}
9646
Antonio Kantek15beb512022-06-13 22:35:41 +00009647TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9648 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9649 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9650 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009651 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009652 mWindow->assertNoEvents();
9653 mSecondWindow->assertNoEvents();
9654 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9655}
9656
Antonio Kantek48710e42022-03-24 14:19:30 -07009657TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9658 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9660 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009661 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9662 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9663
9664 // Then remove focus.
9665 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009666 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009667
9668 // Assert that caller can switch touch mode by owning one of the last interacted window.
9669 const WindowInfo& windowInfo = *mWindow->getInfo();
9670 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9671 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009672 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009673}
9674
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009675class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9676public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009677 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009678 std::shared_ptr<FakeApplicationHandle> application =
9679 std::make_shared<FakeApplicationHandle>();
9680 std::string name = "Fake Spy ";
9681 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009682 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9683 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009684 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009685 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009686 return spy;
9687 }
9688
9689 sp<FakeWindowHandle> createForeground() {
9690 std::shared_ptr<FakeApplicationHandle> application =
9691 std::make_shared<FakeApplicationHandle>();
9692 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009693 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9694 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009695 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009696 return window;
9697 }
9698
9699private:
9700 int mSpyCount{0};
9701};
9702
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009703using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009704/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009705 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9706 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009707TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009708 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009709 ScopedSilentDeath _silentDeath;
9710
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009711 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009712 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009713 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009714 ".* not a trusted overlay");
9715}
9716
9717/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009718 * Input injection into a display with a spy window but no foreground windows should succeed.
9719 */
9720TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009721 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009722 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009723
9724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9727 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9728}
9729
9730/**
9731 * Verify the order in which different input windows receive events. The touched foreground window
9732 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9733 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9734 * receive events before ones belows it.
9735 *
9736 * Here, we set up a scenario with four windows in the following Z order from the top:
9737 * spy1, spy2, window, spy3.
9738 * We then inject an event and verify that the foreground "window" receives it first, followed by
9739 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9740 * window.
9741 */
9742TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9743 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009744 auto spy1 = createSpy();
9745 auto spy2 = createSpy();
9746 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009747 mDispatcher->onWindowInfosChanged(
9748 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009749 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9750 const size_t numChannels = channels.size();
9751
Michael Wright8e9a8562022-02-09 13:44:29 +00009752 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009753 if (!epollFd.ok()) {
9754 FAIL() << "Failed to create epoll fd";
9755 }
9756
9757 for (size_t i = 0; i < numChannels; i++) {
9758 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9759 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9760 FAIL() << "Failed to add fd to epoll";
9761 }
9762 }
9763
9764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009765 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9767
9768 std::vector<size_t> eventOrder;
9769 std::vector<struct epoll_event> events(numChannels);
9770 for (;;) {
9771 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9772 (100ms).count());
9773 if (nFds < 0) {
9774 FAIL() << "Failed to call epoll_wait";
9775 }
9776 if (nFds == 0) {
9777 break; // epoll_wait timed out
9778 }
9779 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009780 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009781 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009782 channels[i]->consumeMotionDown();
9783 }
9784 }
9785
9786 // Verify the order in which the events were received.
9787 EXPECT_EQ(3u, eventOrder.size());
9788 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9789 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9790 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9791}
9792
9793/**
9794 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9795 */
9796TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9797 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009798 auto spy = createSpy();
9799 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009800 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009801
9802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9805 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9806 spy->assertNoEvents();
9807}
9808
9809/**
9810 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9811 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9812 * to the window.
9813 */
9814TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9815 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009816 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009817 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009818 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009819
9820 // Inject an event outside the spy window's touchable region.
9821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009822 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9824 window->consumeMotionDown();
9825 spy->assertNoEvents();
9826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009827 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9829 window->consumeMotionUp();
9830 spy->assertNoEvents();
9831
9832 // Inject an event inside the spy window's touchable region.
9833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009834 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009835 {5, 10}))
9836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9837 window->consumeMotionDown();
9838 spy->consumeMotionDown();
9839}
9840
9841/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009842 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009843 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009844 */
9845TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9846 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009847 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009848 auto spy = createSpy();
9849 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009850 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009851 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009852 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009853
9854 // Inject an event outside the spy window's frame and touchable region.
9855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009856 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009857 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9859 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009860 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009861}
9862
9863/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009864 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9865 * pointers that are down within its bounds.
9866 */
9867TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9868 auto windowLeft = createForeground();
9869 windowLeft->setFrame({0, 0, 100, 200});
9870 auto windowRight = createForeground();
9871 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009872 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009873 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009874 mDispatcher->onWindowInfosChanged(
9875 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009876
9877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009878 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009879 {50, 50}))
9880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9881 windowLeft->consumeMotionDown();
9882 spy->consumeMotionDown();
9883
9884 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009885 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009886 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009887 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9888 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009889 .build();
9890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009891 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009892 InputEventInjectionSync::WAIT_FOR_RESULT))
9893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9894 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009895 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009896}
9897
9898/**
9899 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9900 * the spy should receive the second pointer with ACTION_DOWN.
9901 */
9902TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9903 auto window = createForeground();
9904 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009905 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009906 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009907 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009908
9909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009910 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009911 {50, 50}))
9912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9913 window->consumeMotionDown();
9914 spyRight->assertNoEvents();
9915
9916 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009917 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009918 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009919 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9920 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009921 .build();
9922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009923 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009924 InputEventInjectionSync::WAIT_FOR_RESULT))
9925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009926 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009927 spyRight->consumeMotionDown();
9928}
9929
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009930/**
9931 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9932 * windows should be allowed to control split touch.
9933 */
9934TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009935 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009936 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009937 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009938 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009939
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009940 auto window = createForeground();
9941 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009942
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009943 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009944
9945 // First finger down, no window touched.
9946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009947 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009948 {100, 200}))
9949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9950 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9951 window->assertNoEvents();
9952
9953 // Second finger down on window, the window should receive touch down.
9954 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009955 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009956 .displayId(ADISPLAY_ID_DEFAULT)
9957 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009958 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9959 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009960 .build();
9961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009962 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009963 InputEventInjectionSync::WAIT_FOR_RESULT))
9964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9965
9966 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009967 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009968}
9969
9970/**
9971 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9972 * do not receive key events.
9973 */
9974TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009975 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009976 spy->setFocusable(false);
9977
9978 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009979 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009980 setFocusedWindow(window);
9981 window->consumeFocusEvent(true);
9982
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009984 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9985 window->consumeKeyDown(ADISPLAY_ID_NONE);
9986
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009988 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9989 window->consumeKeyUp(ADISPLAY_ID_NONE);
9990
9991 spy->assertNoEvents();
9992}
9993
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009994using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9995
9996/**
9997 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9998 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9999 */
10000TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10001 auto window = createForeground();
10002 auto spy1 = createSpy();
10003 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010004 mDispatcher->onWindowInfosChanged(
10005 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010006
10007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010008 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10010 window->consumeMotionDown();
10011 spy1->consumeMotionDown();
10012 spy2->consumeMotionDown();
10013
10014 // Pilfer pointers from the second spy window.
10015 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10016 spy2->assertNoEvents();
10017 spy1->consumeMotionCancel();
10018 window->consumeMotionCancel();
10019
10020 // The rest of the gesture should only be sent to the second spy window.
10021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010022 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010023 ADISPLAY_ID_DEFAULT))
10024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10025 spy2->consumeMotionMove();
10026 spy1->assertNoEvents();
10027 window->assertNoEvents();
10028}
10029
10030/**
10031 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10032 * in the middle of the gesture.
10033 */
10034TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10035 auto window = createForeground();
10036 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010037 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010038
10039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010040 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10042 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10043 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10044
10045 window->releaseChannel();
10046
10047 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10048
10049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010050 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10052 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10053}
10054
10055/**
10056 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10057 * the spy, but not to any other windows.
10058 */
10059TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10060 auto spy = createSpy();
10061 auto window = createForeground();
10062
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010063 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010064
10065 // First finger down on the window and the spy.
10066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010067 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010068 {100, 200}))
10069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10070 spy->consumeMotionDown();
10071 window->consumeMotionDown();
10072
10073 // Spy window pilfers the pointers.
10074 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10075 window->consumeMotionCancel();
10076
10077 // Second finger down on the window and spy, but the window should not receive the pointer down.
10078 const MotionEvent secondFingerDownEvent =
10079 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10080 .displayId(ADISPLAY_ID_DEFAULT)
10081 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010082 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10083 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010084 .build();
10085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010086 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010087 InputEventInjectionSync::WAIT_FOR_RESULT))
10088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10089
Harry Cutts33476232023-01-30 19:57:29 +000010090 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010091
10092 // Third finger goes down outside all windows, so injection should fail.
10093 const MotionEvent thirdFingerDownEvent =
10094 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10095 .displayId(ADISPLAY_ID_DEFAULT)
10096 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010097 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10098 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10099 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010100 .build();
10101 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010102 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010103 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010104 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010105
10106 spy->assertNoEvents();
10107 window->assertNoEvents();
10108}
10109
10110/**
10111 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10112 */
10113TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10114 auto spy = createSpy();
10115 spy->setFrame(Rect(0, 0, 100, 100));
10116 auto window = createForeground();
10117 window->setFrame(Rect(0, 0, 200, 200));
10118
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010119 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010120
10121 // First finger down on the window only
10122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010123 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010124 {150, 150}))
10125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10126 window->consumeMotionDown();
10127
10128 // Second finger down on the spy and window
10129 const MotionEvent secondFingerDownEvent =
10130 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10131 .displayId(ADISPLAY_ID_DEFAULT)
10132 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010133 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10134 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010135 .build();
10136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010137 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010138 InputEventInjectionSync::WAIT_FOR_RESULT))
10139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10140 spy->consumeMotionDown();
10141 window->consumeMotionPointerDown(1);
10142
10143 // Third finger down on the spy and window
10144 const MotionEvent thirdFingerDownEvent =
10145 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10146 .displayId(ADISPLAY_ID_DEFAULT)
10147 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010148 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10149 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10150 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010151 .build();
10152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010153 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010154 InputEventInjectionSync::WAIT_FOR_RESULT))
10155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10156 spy->consumeMotionPointerDown(1);
10157 window->consumeMotionPointerDown(2);
10158
10159 // Spy window pilfers the pointers.
10160 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010161 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10162 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010163
10164 spy->assertNoEvents();
10165 window->assertNoEvents();
10166}
10167
10168/**
10169 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10170 * other windows should be canceled. If this results in the cancellation of all pointers for some
10171 * window, then that window should receive ACTION_CANCEL.
10172 */
10173TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10174 auto spy = createSpy();
10175 spy->setFrame(Rect(0, 0, 100, 100));
10176 auto window = createForeground();
10177 window->setFrame(Rect(0, 0, 200, 200));
10178
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010179 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010180
10181 // First finger down on both spy and window
10182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010184 {10, 10}))
10185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10186 window->consumeMotionDown();
10187 spy->consumeMotionDown();
10188
10189 // Second finger down on the spy and window
10190 const MotionEvent secondFingerDownEvent =
10191 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10192 .displayId(ADISPLAY_ID_DEFAULT)
10193 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10195 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010196 .build();
10197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010198 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010199 InputEventInjectionSync::WAIT_FOR_RESULT))
10200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10201 spy->consumeMotionPointerDown(1);
10202 window->consumeMotionPointerDown(1);
10203
10204 // Spy window pilfers the pointers.
10205 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10206 window->consumeMotionCancel();
10207
10208 spy->assertNoEvents();
10209 window->assertNoEvents();
10210}
10211
10212/**
10213 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10214 * be sent to other windows
10215 */
10216TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10217 auto spy = createSpy();
10218 spy->setFrame(Rect(0, 0, 100, 100));
10219 auto window = createForeground();
10220 window->setFrame(Rect(0, 0, 200, 200));
10221
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010222 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010223
10224 // First finger down on both window and spy
10225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010226 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010227 {10, 10}))
10228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10229 window->consumeMotionDown();
10230 spy->consumeMotionDown();
10231
10232 // Spy window pilfers the pointers.
10233 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10234 window->consumeMotionCancel();
10235
10236 // Second finger down on the window only
10237 const MotionEvent secondFingerDownEvent =
10238 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10239 .displayId(ADISPLAY_ID_DEFAULT)
10240 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010241 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10242 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010243 .build();
10244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010245 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010246 InputEventInjectionSync::WAIT_FOR_RESULT))
10247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10248 window->consumeMotionDown();
10249 window->assertNoEvents();
10250
10251 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10252 spy->consumeMotionMove();
10253 spy->assertNoEvents();
10254}
10255
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010256/**
10257 * A window on the left and a window on the right. Also, a spy window that's above all of the
10258 * windows, and spanning both left and right windows.
10259 * Send simultaneous motion streams from two different devices, one to the left window, and another
10260 * to the right window.
10261 * Pilfer from spy window.
10262 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10263 */
10264TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10265 sp<FakeWindowHandle> spy = createSpy();
10266 spy->setFrame(Rect(0, 0, 200, 200));
10267 sp<FakeWindowHandle> leftWindow = createForeground();
10268 leftWindow->setFrame(Rect(0, 0, 100, 100));
10269
10270 sp<FakeWindowHandle> rightWindow = createForeground();
10271 rightWindow->setFrame(Rect(100, 0, 200, 100));
10272
10273 constexpr int32_t stylusDeviceId = 1;
10274 constexpr int32_t touchDeviceId = 2;
10275
10276 mDispatcher->onWindowInfosChanged(
10277 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10278
10279 // Stylus down on left window and spy
10280 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10281 .deviceId(stylusDeviceId)
10282 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10283 .build());
10284 leftWindow->consumeMotionEvent(
10285 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10286 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10287
10288 // Finger down on right window and spy - but spy already has stylus
10289 mDispatcher->notifyMotion(
10290 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10291 .deviceId(touchDeviceId)
10292 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10293 .build());
10294 rightWindow->consumeMotionEvent(
10295 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10296 leftWindow->consumeMotionEvent(
10297 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10298 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10299 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10300
10301 // Act: pilfer from spy. Spy is currently receiving touch events.
10302 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10303 rightWindow->consumeMotionEvent(
10304 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10305
10306 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10307 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10308 .deviceId(stylusDeviceId)
10309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10310 .build());
10311 mDispatcher->notifyMotion(
10312 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10313 .deviceId(touchDeviceId)
10314 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10315 .build());
10316 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10317
10318 spy->assertNoEvents();
10319 leftWindow->assertNoEvents();
10320 rightWindow->assertNoEvents();
10321}
10322
Prabir Pradhand65552b2021-10-07 11:23:50 -070010323class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10324public:
10325 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10326 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10327 std::make_shared<FakeApplicationHandle>();
10328 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010329 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10330 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010331 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010332 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010333 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010334 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010335 overlay->setTrustedOverlay(true);
10336
10337 std::shared_ptr<FakeApplicationHandle> application =
10338 std::make_shared<FakeApplicationHandle>();
10339 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010340 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10341 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010342 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010343 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010344
10345 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010346 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010347 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010348 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010349 return {std::move(overlay), std::move(window)};
10350 }
10351
10352 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010353 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010354 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010355 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010356 }
10357
10358 void sendStylusEvent(int32_t action) {
10359 NotifyMotionArgs motionArgs =
10360 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10361 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010362 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010363 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010364 }
10365};
10366
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010367using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10368
10369TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010370 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010371 ScopedSilentDeath _silentDeath;
10372
Prabir Pradhand65552b2021-10-07 11:23:50 -070010373 auto [overlay, window] = setupStylusOverlayScenario();
10374 overlay->setTrustedOverlay(false);
10375 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010376 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10377 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010378 ".* not a trusted overlay");
10379}
10380
10381TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10382 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010383 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010384
10385 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10386 overlay->consumeMotionDown();
10387 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10388 overlay->consumeMotionUp();
10389
10390 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10391 window->consumeMotionDown();
10392 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10393 window->consumeMotionUp();
10394
10395 overlay->assertNoEvents();
10396 window->assertNoEvents();
10397}
10398
10399TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10400 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010401 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010402 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010403
10404 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10405 overlay->consumeMotionDown();
10406 window->consumeMotionDown();
10407 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10408 overlay->consumeMotionUp();
10409 window->consumeMotionUp();
10410
10411 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10412 window->consumeMotionDown();
10413 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10414 window->consumeMotionUp();
10415
10416 overlay->assertNoEvents();
10417 window->assertNoEvents();
10418}
10419
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010420/**
10421 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10422 * The scenario is as follows:
10423 * - The stylus interceptor overlay is configured as a spy window.
10424 * - The stylus interceptor spy receives the start of a new stylus gesture.
10425 * - It pilfers pointers and then configures itself to no longer be a spy.
10426 * - The stylus interceptor continues to receive the rest of the gesture.
10427 */
10428TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10429 auto [overlay, window] = setupStylusOverlayScenario();
10430 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010431 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010432
10433 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10434 overlay->consumeMotionDown();
10435 window->consumeMotionDown();
10436
10437 // The interceptor pilfers the pointers.
10438 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10439 window->consumeMotionCancel();
10440
10441 // The interceptor configures itself so that it is no longer a spy.
10442 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010443 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010444
10445 // It continues to receive the rest of the stylus gesture.
10446 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10447 overlay->consumeMotionMove();
10448 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10449 overlay->consumeMotionUp();
10450
10451 window->assertNoEvents();
10452}
10453
Prabir Pradhan5735a322022-04-11 17:23:34 +000010454struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010455 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010456 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010457 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10458 std::unique_ptr<InputDispatcher>& mDispatcher;
10459
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010460 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010461 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10462
10463 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010464 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010465 ADISPLAY_ID_DEFAULT, {100, 200},
10466 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10467 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10468 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10469 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10470 }
10471
10472 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010473 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010474 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010475 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010476 mPolicyFlags);
10477 }
10478
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010479 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010480 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10481 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010482 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10483 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010484 window->setOwnerInfo(mPid, mUid);
10485 return window;
10486 }
10487};
10488
10489using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10490
10491TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010492 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010493 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010494 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010495
10496 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10497 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10498 window->consumeMotionDown();
10499
10500 setFocusedWindow(window);
10501 window->consumeFocusEvent(true);
10502
10503 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10504 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10505 window->consumeKeyDown(ADISPLAY_ID_NONE);
10506}
10507
10508TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010509 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010510 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010511 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010512
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010513 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010514 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10515 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10516
10517 setFocusedWindow(window);
10518 window->consumeFocusEvent(true);
10519
10520 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10521 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10522 window->assertNoEvents();
10523}
10524
10525TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010526 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010527 auto window = owner.createWindow("Owned window");
10528 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010529 spy->setSpy(true);
10530 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010531 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010532
10533 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10534 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10535 spy->consumeMotionDown();
10536 window->consumeMotionDown();
10537}
10538
10539TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010540 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010541 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010542
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010543 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010544 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010545 randosSpy->setSpy(true);
10546 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010547 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010548
10549 // The event is targeted at owner's window, so injection should succeed, but the spy should
10550 // not receive the event.
10551 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10552 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10553 randosSpy->assertNoEvents();
10554 window->consumeMotionDown();
10555}
10556
10557TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010558 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010559 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010560
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010561 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010562 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010563 randosSpy->setSpy(true);
10564 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010565 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010566
10567 // A user that has injection permission can inject into any window.
10568 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010569 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010570 ADISPLAY_ID_DEFAULT));
10571 randosSpy->consumeMotionDown();
10572 window->consumeMotionDown();
10573
10574 setFocusedWindow(randosSpy);
10575 randosSpy->consumeFocusEvent(true);
10576
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010577 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010578 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10579 window->assertNoEvents();
10580}
10581
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010582TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010583 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010584 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010585
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010586 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010587 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010588 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10589 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010590 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010591
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010592 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010593 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10594 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10595 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010596 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010597}
10598
Garfield Tane84e6f92019-08-29 17:28:41 -070010599} // namespace android::inputdispatcher