blob: 3c87f7194dbe4a2df10b86de4cc7149aa4190008 [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/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002412 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2413 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002414 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002415TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2417 sp<FakeWindowHandle> window =
2418 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2419 window->setFrame(Rect(0, 0, 200, 200));
2420
2421 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2422
2423 constexpr int32_t touchDeviceId = 4;
2424 constexpr int32_t stylusDeviceId = 2;
2425
2426 // Stylus down
2427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2428 .deviceId(stylusDeviceId)
2429 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2430 .build());
2431 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2432
2433 // Touch down
2434 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2435 .deviceId(touchDeviceId)
2436 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2437 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002438
2439 // Touch move
2440 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2441 .deviceId(touchDeviceId)
2442 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2443 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002444 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002445
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002446 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2448 .deviceId(stylusDeviceId)
2449 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2450 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002451 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2452 WithCoords(101, 111)));
2453
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002454 window->assertNoEvents();
2455}
2456
2457/**
2458 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002459 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002460 * Similar test as above, but with added SPY window.
2461 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002462TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 sp<FakeWindowHandle> spyWindow =
2467 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2468 spyWindow->setFrame(Rect(0, 0, 200, 200));
2469 spyWindow->setTrustedOverlay(true);
2470 spyWindow->setSpy(true);
2471 window->setFrame(Rect(0, 0, 200, 200));
2472
2473 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2474
2475 constexpr int32_t touchDeviceId = 4;
2476 constexpr int32_t stylusDeviceId = 2;
2477
2478 // Stylus down
2479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2480 .deviceId(stylusDeviceId)
2481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2482 .build());
2483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2484 spyWindow->consumeMotionEvent(
2485 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2486
2487 // Touch down
2488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2491 .build());
2492
2493 // Touch move
2494 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2495 .deviceId(touchDeviceId)
2496 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2497 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002498
2499 // Touch is ignored because stylus is already down
2500
2501 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2503 .deviceId(stylusDeviceId)
2504 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2505 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002506 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2507 WithCoords(101, 111)));
2508 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2509 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002510
2511 window->assertNoEvents();
2512 spyWindow->assertNoEvents();
2513}
2514
2515/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002516 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2517 * touch is not dropped, because stylus hover should be ignored.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002518 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002519TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2521 sp<FakeWindowHandle> window =
2522 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2523 window->setFrame(Rect(0, 0, 200, 200));
2524
2525 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2526
2527 constexpr int32_t touchDeviceId = 4;
2528 constexpr int32_t stylusDeviceId = 2;
2529
2530 // Stylus down on the window
2531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2532 .deviceId(stylusDeviceId)
2533 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2534 .build());
2535 window->consumeMotionEvent(
2536 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2537
2538 // Touch down on window
2539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2540 .deviceId(touchDeviceId)
2541 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2542 .build());
2543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2544 .deviceId(touchDeviceId)
2545 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2546 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002547
2548 // Stylus hover is canceled because touch is down
2549 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT),
2550 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2552 WithCoords(140, 145)));
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2554 WithCoords(141, 146)));
2555
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002556 // Subsequent stylus movements are ignored
2557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2558 .deviceId(stylusDeviceId)
2559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2560 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002561
2562 // but subsequent touches continue to be delivered
2563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2564 .deviceId(touchDeviceId)
2565 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2566 .build());
2567 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2568 WithCoords(142, 147)));
2569}
2570
2571/**
2572 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2573 * Ensure that touch is not canceled, because stylus hover should be dropped.
2574 */
2575TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2577 sp<FakeWindowHandle> window =
2578 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2579 window->setFrame(Rect(0, 0, 200, 200));
2580
2581 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2582
2583 constexpr int32_t touchDeviceId = 4;
2584 constexpr int32_t stylusDeviceId = 2;
2585
2586 // Touch down on window
2587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2588 .deviceId(touchDeviceId)
2589 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2590 .build());
2591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2592 .deviceId(touchDeviceId)
2593 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2594 .build());
2595 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2596 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2597
2598 // Stylus hover on the window
2599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2600 .deviceId(stylusDeviceId)
2601 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2602 .build());
2603 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2604 .deviceId(stylusDeviceId)
2605 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2606 .build());
2607 // Stylus hover movement is dropped
2608
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2612 .build());
2613 // Subsequent touch movements are delivered correctly
2614 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2615 WithCoords(142, 147)));
2616}
2617
2618/**
2619 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2620 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2621 * become active.
2622 */
2623TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2625 sp<FakeWindowHandle> window =
2626 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2627 window->setFrame(Rect(0, 0, 200, 200));
2628
2629 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2630
2631 constexpr int32_t stylusDeviceId1 = 3;
2632 constexpr int32_t stylusDeviceId2 = 5;
2633
2634 // Touch down on window
2635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2636 .deviceId(stylusDeviceId1)
2637 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2638 .build());
2639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2640 .deviceId(stylusDeviceId1)
2641 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2642 .build());
2643 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2644 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2645
2646 // Second stylus down
2647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2648 .deviceId(stylusDeviceId2)
2649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2650 .build());
2651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2652 .deviceId(stylusDeviceId2)
2653 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2654 .build());
2655
2656 // First stylus is canceled, second one takes over.
2657 window->consumeMotionEvent(
2658 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2659 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2660 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2661
2662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2663 .deviceId(stylusDeviceId1)
2664 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2665 .build());
2666 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002667 window->assertNoEvents();
2668}
2669
2670/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002671 * One window. Touch down on the window. Then, stylus down on the window from another device.
2672 * Ensure that is canceled, because stylus down should be preferred over touch.
2673 */
2674TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2676 sp<FakeWindowHandle> window =
2677 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2678 window->setFrame(Rect(0, 0, 200, 200));
2679
2680 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2681
2682 constexpr int32_t touchDeviceId = 4;
2683 constexpr int32_t stylusDeviceId = 2;
2684
2685 // Touch down on window
2686 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2687 .deviceId(touchDeviceId)
2688 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2689 .build());
2690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2691 .deviceId(touchDeviceId)
2692 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2693 .build());
2694 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2695 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2696
2697 // Stylus down on the window
2698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2699 .deviceId(stylusDeviceId)
2700 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2701 .build());
2702 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2703 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2704
2705 // Subsequent stylus movements are delivered correctly
2706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2707 .deviceId(stylusDeviceId)
2708 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2709 .build());
2710 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2711 WithCoords(101, 111)));
2712}
2713
2714/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002715 * Two windows: a window on the left and a window on the right.
2716 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2717 * down. Then, on the left window, also place second touch pointer down.
2718 * This test tries to reproduce a crash.
2719 * In the buggy implementation, second pointer down on the left window would cause a crash.
2720 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002721TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2723 sp<FakeWindowHandle> leftWindow =
2724 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2725 leftWindow->setFrame(Rect(0, 0, 200, 200));
2726
2727 sp<FakeWindowHandle> rightWindow =
2728 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2729 rightWindow->setFrame(Rect(200, 0, 400, 200));
2730
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002731 mDispatcher->onWindowInfosChanged(
2732 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002733
2734 const int32_t touchDeviceId = 4;
2735 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002736
2737 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2739 .deviceId(mouseDeviceId)
2740 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2741 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002742 leftWindow->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2744
2745 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2747 .deviceId(mouseDeviceId)
2748 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2749 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2750 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002751
2752 leftWindow->consumeMotionEvent(
2753 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2754 leftWindow->consumeMotionEvent(
2755 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2756
Prabir Pradhan678438e2023-04-13 19:32:51 +00002757 mDispatcher->notifyMotion(
2758 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2759 .deviceId(mouseDeviceId)
2760 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2761 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2762 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2763 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002764 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2765
2766 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2768 .deviceId(touchDeviceId)
2769 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2770 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002771 leftWindow->assertNoEvents();
2772
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002773 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2774
2775 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002776 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2777 .deviceId(touchDeviceId)
2778 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2779 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2780 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002781 // Since this is now a new splittable pointer going down on the left window, and it's coming
2782 // from a different device, the current gesture in the left window (pointer down) should first
2783 // be canceled.
2784 leftWindow->consumeMotionEvent(
2785 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002786 leftWindow->consumeMotionEvent(
2787 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2788 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2789 // current implementation.
2790 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2791 rightWindow->consumeMotionEvent(
2792 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2793
2794 leftWindow->assertNoEvents();
2795 rightWindow->assertNoEvents();
2796}
2797
2798/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002799 * Two windows: a window on the left and a window on the right.
2800 * Mouse is hovered on the left window and stylus is hovered on the right window.
2801 */
2802TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2804 sp<FakeWindowHandle> leftWindow =
2805 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2806 leftWindow->setFrame(Rect(0, 0, 200, 200));
2807
2808 sp<FakeWindowHandle> rightWindow =
2809 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2810 rightWindow->setFrame(Rect(200, 0, 400, 200));
2811
2812 mDispatcher->onWindowInfosChanged(
2813 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2814
2815 const int32_t stylusDeviceId = 3;
2816 const int32_t mouseDeviceId = 6;
2817
2818 // Start hovering over the left window
2819 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2820 .deviceId(mouseDeviceId)
2821 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2822 .build());
2823 leftWindow->consumeMotionEvent(
2824 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2825
2826 // Stylus hovered on right window
2827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2828 .deviceId(stylusDeviceId)
2829 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2830 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002831 rightWindow->consumeMotionEvent(
2832 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2833
2834 // Subsequent HOVER_MOVE events are dispatched correctly.
2835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2836 .deviceId(mouseDeviceId)
2837 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2838 .build());
2839 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002840 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002841
2842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2843 .deviceId(stylusDeviceId)
2844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2845 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002846 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002847 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002848
2849 leftWindow->assertNoEvents();
2850 rightWindow->assertNoEvents();
2851}
2852
2853/**
2854 * Three windows: a window on the left and a window on the right.
2855 * And a spy window that's positioned above all of them.
2856 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2857 * Check the stream that's received by the spy.
2858 */
2859TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2861
2862 sp<FakeWindowHandle> spyWindow =
2863 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2864 spyWindow->setFrame(Rect(0, 0, 400, 400));
2865 spyWindow->setTrustedOverlay(true);
2866 spyWindow->setSpy(true);
2867
2868 sp<FakeWindowHandle> leftWindow =
2869 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2870 leftWindow->setFrame(Rect(0, 0, 200, 200));
2871
2872 sp<FakeWindowHandle> rightWindow =
2873 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2874
2875 rightWindow->setFrame(Rect(200, 0, 400, 200));
2876
2877 mDispatcher->onWindowInfosChanged(
2878 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2879
2880 const int32_t stylusDeviceId = 1;
2881 const int32_t touchDeviceId = 2;
2882
2883 // Stylus down on the left window
2884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2885 .deviceId(stylusDeviceId)
2886 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2887 .build());
2888 leftWindow->consumeMotionEvent(
2889 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2890 spyWindow->consumeMotionEvent(
2891 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2892
2893 // Touch down on the right window
2894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2895 .deviceId(touchDeviceId)
2896 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2897 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002898 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002899 rightWindow->consumeMotionEvent(
2900 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002901
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002902 // Spy window does not receive touch events, because stylus events take precedence, and it
2903 // already has an active stylus gesture.
2904
2905 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2907 .deviceId(stylusDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2909 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002910 leftWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2912 spyWindow->consumeMotionEvent(
2913 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002914
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002915 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2917 .deviceId(touchDeviceId)
2918 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2919 .build());
2920 rightWindow->consumeMotionEvent(
2921 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002922
2923 spyWindow->assertNoEvents();
2924 leftWindow->assertNoEvents();
2925 rightWindow->assertNoEvents();
2926}
2927
2928/**
2929 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2930 * both.
2931 * Check hover in left window and touch down in the right window.
2932 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002933 * At the same time, left and right should be getting independent streams of hovering and touch,
2934 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002936TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlockedByTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2938
2939 sp<FakeWindowHandle> spyWindow =
2940 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2941 spyWindow->setFrame(Rect(0, 0, 400, 400));
2942 spyWindow->setTrustedOverlay(true);
2943 spyWindow->setSpy(true);
2944
2945 sp<FakeWindowHandle> leftWindow =
2946 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2947 leftWindow->setFrame(Rect(0, 0, 200, 200));
2948
2949 sp<FakeWindowHandle> rightWindow =
2950 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2951 rightWindow->setFrame(Rect(200, 0, 400, 200));
2952
2953 mDispatcher->onWindowInfosChanged(
2954 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2955
2956 const int32_t stylusDeviceId = 1;
2957 const int32_t touchDeviceId = 2;
2958
2959 // Stylus hover on the left window
2960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2961 .deviceId(stylusDeviceId)
2962 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2963 .build());
2964 leftWindow->consumeMotionEvent(
2965 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2966 spyWindow->consumeMotionEvent(
2967 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2968
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002969 // Touch down on the right window. Spy doesn't receive this touch because it already has
2970 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2972 .deviceId(touchDeviceId)
2973 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2974 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002975 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002976 spyWindow->consumeMotionEvent(
2977 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2978 spyWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2980 rightWindow->consumeMotionEvent(
2981 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2982
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002983 // Stylus movements continue. They should be delivered to the left window only.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2985 .deviceId(stylusDeviceId)
2986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2987 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002988 leftWindow->consumeMotionEvent(
2989 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002990
2991 // Touch movements continue. They should be delivered to the right window and to the spy
2992 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2993 .deviceId(touchDeviceId)
2994 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2995 .build());
2996 spyWindow->consumeMotionEvent(
2997 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2998 rightWindow->consumeMotionEvent(
2999 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3000
3001 spyWindow->assertNoEvents();
3002 leftWindow->assertNoEvents();
3003 rightWindow->assertNoEvents();
3004}
3005
3006/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003007 * On a single window, use two different devices: mouse and touch.
3008 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3009 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3010 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3011 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3012 * represent a new gesture.
3013 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003014TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3016 sp<FakeWindowHandle> window =
3017 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3018 window->setFrame(Rect(0, 0, 400, 400));
3019
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003020 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003021
3022 const int32_t touchDeviceId = 4;
3023 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003024
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003025 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3027 .deviceId(touchDeviceId)
3028 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3029 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003030 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003031 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3032 .deviceId(touchDeviceId)
3033 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3034 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3035 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003036 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003037 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3038 .deviceId(touchDeviceId)
3039 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3040 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3041 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003042 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3043 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3044 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3045
3046 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3048 .deviceId(mouseDeviceId)
3049 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3050 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3051 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003052
3053 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003054 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003055 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3056
Prabir Pradhan678438e2023-04-13 19:32:51 +00003057 mDispatcher->notifyMotion(
3058 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3059 .deviceId(mouseDeviceId)
3060 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3061 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3062 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3063 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003064 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3065
3066 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003067 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3068 .deviceId(touchDeviceId)
3069 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3070 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3071 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003072 // Since we already canceled this touch gesture, it will be ignored until a completely new
3073 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3074 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3075 // However, mouse movements should continue to work.
3076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3077 .deviceId(mouseDeviceId)
3078 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3079 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3080 .build());
3081 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3082
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003083 window->assertNoEvents();
3084}
3085
3086/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003087 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3088 * the injected event.
3089 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003090TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3092 sp<FakeWindowHandle> window =
3093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3094 window->setFrame(Rect(0, 0, 400, 400));
3095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003097
3098 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003099 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3100 // completion.
3101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003102 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003103 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3104 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003105 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003106 .build()));
3107 window->consumeMotionEvent(
3108 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3109
3110 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3111 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003112 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3113 .deviceId(touchDeviceId)
3114 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3115 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003116
3117 window->consumeMotionEvent(
3118 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3119 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3120}
3121
3122/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003123 * This test is similar to the test above, but the sequence of injected events is different.
3124 *
3125 * Two windows: a window on the left and a window on the right.
3126 * Mouse is hovered over the left window.
3127 * Next, we tap on the left window, where the cursor was last seen.
3128 *
3129 * After that, we inject one finger down onto the right window, and then a second finger down onto
3130 * the left window.
3131 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3132 * window (first), and then another on the left window (second).
3133 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3134 * In the buggy implementation, second finger down on the left window would cause a crash.
3135 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003136TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3138 sp<FakeWindowHandle> leftWindow =
3139 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3140 leftWindow->setFrame(Rect(0, 0, 200, 200));
3141
3142 sp<FakeWindowHandle> rightWindow =
3143 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3144 rightWindow->setFrame(Rect(200, 0, 400, 200));
3145
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003146 mDispatcher->onWindowInfosChanged(
3147 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003148
3149 const int32_t mouseDeviceId = 6;
3150 const int32_t touchDeviceId = 4;
3151 // Hover over the left window. Keep the cursor there.
3152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003153 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003154 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3155 AINPUT_SOURCE_MOUSE)
3156 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003157 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003158 .build()));
3159 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3160
3161 // Tap on left window
3162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003163 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003164 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3165 AINPUT_SOURCE_TOUCHSCREEN)
3166 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003167 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003168 .build()));
3169
3170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003171 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003172 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3173 AINPUT_SOURCE_TOUCHSCREEN)
3174 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003175 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003176 .build()));
3177 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3178 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3179 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3180
3181 // First finger down on right window
3182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003183 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003184 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3185 AINPUT_SOURCE_TOUCHSCREEN)
3186 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003187 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003188 .build()));
3189 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3190
3191 // Second finger down on the left window
3192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003193 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003194 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3195 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003196 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3197 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003198 .build()));
3199 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3200 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3201
3202 // No more events
3203 leftWindow->assertNoEvents();
3204 rightWindow->assertNoEvents();
3205}
3206
3207/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003208 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3209 * While the touch is down, new hover events from the stylus device should be ignored. After the
3210 * touch is gone, stylus hovering should start working again.
3211 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003212TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDroppedWhenTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3214 sp<FakeWindowHandle> window =
3215 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3216 window->setFrame(Rect(0, 0, 200, 200));
3217
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003218 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003219
3220 const int32_t stylusDeviceId = 5;
3221 const int32_t touchDeviceId = 4;
3222 // Start hovering with stylus
3223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003224 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003225 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003226 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003227 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003228 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003229 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003230
3231 // Finger down on the window
3232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003233 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003234 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003235 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003236 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003237 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003238 // The touch device should cause hover to stop!
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003239 window->consumeMotionEvent(
3240 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3241 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003242
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003243 // Continue hovering with stylus.
3244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003245 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003246 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3247 AINPUT_SOURCE_STYLUS)
3248 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003249 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003250 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003251 // Hovers are now ignored
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003252
3253 // Lift up the finger
3254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003255 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003256 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3257 AINPUT_SOURCE_TOUCHSCREEN)
3258 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003260 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003261 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003262
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003264 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003265 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3266 AINPUT_SOURCE_STYLUS)
3267 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003268 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003269 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003270 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3271 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003272 window->assertNoEvents();
3273}
3274
3275/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003276 * A spy window above a window with no input channel.
3277 * Start hovering with a stylus device, and then tap with it.
3278 * Ensure spy window receives the entire sequence.
3279 */
3280TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3282 sp<FakeWindowHandle> spyWindow =
3283 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3284 spyWindow->setFrame(Rect(0, 0, 200, 200));
3285 spyWindow->setTrustedOverlay(true);
3286 spyWindow->setSpy(true);
3287 sp<FakeWindowHandle> window =
3288 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3289 window->setNoInputChannel(true);
3290 window->setFrame(Rect(0, 0, 200, 200));
3291
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003292 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003293
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003294 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003295 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3296 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3297 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003298 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3299 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3301 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3302 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003303 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3304
3305 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3307 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3308 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003309 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3310
3311 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3313 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3314 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003315 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3316
3317 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3319 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3320 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003321 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3322 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003323 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3324 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3325 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003326 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3327
3328 // No more events
3329 spyWindow->assertNoEvents();
3330 window->assertNoEvents();
3331}
3332
3333/**
3334 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3335 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3336 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3337 * While the mouse is down, new move events from the touch device should be ignored.
3338 */
3339TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3341 sp<FakeWindowHandle> spyWindow =
3342 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3343 spyWindow->setFrame(Rect(0, 0, 200, 200));
3344 spyWindow->setTrustedOverlay(true);
3345 spyWindow->setSpy(true);
3346 sp<FakeWindowHandle> window =
3347 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3348 window->setFrame(Rect(0, 0, 200, 200));
3349
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003350 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003351
3352 const int32_t mouseDeviceId = 7;
3353 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003354
3355 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003356 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3357 .deviceId(mouseDeviceId)
3358 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3359 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003360 spyWindow->consumeMotionEvent(
3361 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3362 window->consumeMotionEvent(
3363 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3364
3365 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003366 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3367 .deviceId(touchDeviceId)
3368 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3369 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003370 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3371 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3372 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3373 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3374
Prabir Pradhan678438e2023-04-13 19:32:51 +00003375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3376 .deviceId(touchDeviceId)
3377 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3378 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003379 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3380 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3381
3382 // Pilfer the stream
3383 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3384 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3385
Prabir Pradhan678438e2023-04-13 19:32:51 +00003386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3387 .deviceId(touchDeviceId)
3388 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3389 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003390 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3391
3392 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3394 .deviceId(mouseDeviceId)
3395 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3396 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3397 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003398
3399 spyWindow->consumeMotionEvent(
3400 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3401 spyWindow->consumeMotionEvent(
3402 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3403 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3404
Prabir Pradhan678438e2023-04-13 19:32:51 +00003405 mDispatcher->notifyMotion(
3406 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3407 .deviceId(mouseDeviceId)
3408 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3409 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3410 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3411 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003412 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3413 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3414
3415 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003416 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3417 .deviceId(mouseDeviceId)
3418 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3420 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003421 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3422 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3423
3424 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003425 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3426 .deviceId(touchDeviceId)
3427 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3428 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003429
3430 // No more events
3431 spyWindow->assertNoEvents();
3432 window->assertNoEvents();
3433}
3434
3435/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003436 * On the display, have a single window, and also an area where there's no window.
3437 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3438 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3439 */
3440TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3441 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3442 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003443 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003444
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003445 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003446
3447 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003448 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003449
3450 mDispatcher->waitForIdle();
3451 window->assertNoEvents();
3452
3453 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003454 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003455 mDispatcher->waitForIdle();
3456 window->consumeMotionDown();
3457}
3458
3459/**
3460 * Same test as above, but instead of touching the empty space, the first touch goes to
3461 * non-touchable window.
3462 */
3463TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3465 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003466 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003467 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3468 window1->setTouchable(false);
3469 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003470 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003471 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3472
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003473 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003474
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003475 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003476 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003477
3478 mDispatcher->waitForIdle();
3479 window1->assertNoEvents();
3480 window2->assertNoEvents();
3481
3482 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003483 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003484 mDispatcher->waitForIdle();
3485 window2->consumeMotionDown();
3486}
3487
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003488/**
3489 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3490 * to the event time of the first ACTION_DOWN sent to the particular window.
3491 */
3492TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3494 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003495 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003496 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3497 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003498 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003499 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3500
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003501 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003502
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003503 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003504 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003505
3506 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003507
3508 MotionEvent* motionEvent1 = window1->consumeMotion();
3509 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003510 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003511 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3512 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003513
3514 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003515 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003516 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003517 MotionEvent* motionEvent2 = window2->consumeMotion();
3518 ASSERT_NE(motionEvent2, nullptr);
3519 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003520 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003521 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003522
3523 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003524 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003525 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003526 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003527
3528 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003529 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003530 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003531 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003532
3533 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3534 window1->consumeMotionMove();
3535 window1->assertNoEvents();
3536
3537 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003538 mDispatcher->notifyMotion(
3539 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003540 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003541 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003542
Prabir Pradhan678438e2023-04-13 19:32:51 +00003543 mDispatcher->notifyMotion(
3544 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003545 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003546 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003547}
3548
Garfield Tandf26e862020-07-01 20:18:19 -07003549TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003551 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003552 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003553 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003554 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003555 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003556 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003557
3558 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3559
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003560 mDispatcher->onWindowInfosChanged(
3561 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003562
3563 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003565 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003566 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3567 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003568 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003569 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003570 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003571
3572 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003574 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003575 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3576 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003577 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003578 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003579 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3580 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003581
3582 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003584 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003585 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3586 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003587 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003588 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003589 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3590 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003591
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003593 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003594 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3595 AINPUT_SOURCE_MOUSE)
3596 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3597 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003598 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003599 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003600 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003601
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003603 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003604 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3605 AINPUT_SOURCE_MOUSE)
3606 .buttonState(0)
3607 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003608 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003609 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003610 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003611
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003613 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003614 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3615 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003616 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003617 .build()));
3618 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3619
3620 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003622 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003623 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3624 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003625 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003626 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003627 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003628
3629 // No more events
3630 windowLeft->assertNoEvents();
3631 windowRight->assertNoEvents();
3632}
3633
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003634/**
3635 * Put two fingers down (and don't release them) and click the mouse button.
3636 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3637 * currently active gesture should be canceled, and the new one should proceed.
3638 */
3639TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3640 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3641 sp<FakeWindowHandle> window =
3642 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3643 window->setFrame(Rect(0, 0, 600, 800));
3644
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003645 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003646
3647 const int32_t touchDeviceId = 4;
3648 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003649
3650 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3652 .deviceId(touchDeviceId)
3653 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3654 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003655
Prabir Pradhan678438e2023-04-13 19:32:51 +00003656 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3657 .deviceId(touchDeviceId)
3658 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3659 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3660 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003661 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3662 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3663
3664 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3666 .deviceId(mouseDeviceId)
3667 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3668 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3669 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003670 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3671 WithPointerCount(2u)));
3672 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3673
Prabir Pradhan678438e2023-04-13 19:32:51 +00003674 mDispatcher->notifyMotion(
3675 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3676 .deviceId(mouseDeviceId)
3677 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3678 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3679 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3680 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003681 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3682
3683 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3684 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003685 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3686 .deviceId(touchDeviceId)
3687 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3688 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3689 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003690 window->assertNoEvents();
3691}
3692
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003693TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3695
3696 sp<FakeWindowHandle> spyWindow =
3697 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3698 spyWindow->setFrame(Rect(0, 0, 600, 800));
3699 spyWindow->setTrustedOverlay(true);
3700 spyWindow->setSpy(true);
3701 sp<FakeWindowHandle> window =
3702 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3703 window->setFrame(Rect(0, 0, 600, 800));
3704
3705 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003706 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003707
3708 // Send mouse cursor to the window
3709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003710 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003711 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3712 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003713 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003714 .build()));
3715
3716 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3717 WithSource(AINPUT_SOURCE_MOUSE)));
3718 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3719 WithSource(AINPUT_SOURCE_MOUSE)));
3720
3721 window->assertNoEvents();
3722 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003723}
3724
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003725TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3727
3728 sp<FakeWindowHandle> spyWindow =
3729 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3730 spyWindow->setFrame(Rect(0, 0, 600, 800));
3731 spyWindow->setTrustedOverlay(true);
3732 spyWindow->setSpy(true);
3733 sp<FakeWindowHandle> window =
3734 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3735 window->setFrame(Rect(0, 0, 600, 800));
3736
3737 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003738 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003739
3740 // Send mouse cursor to the window
3741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003742 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003743 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3744 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003745 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003746 .build()));
3747
3748 // Move mouse cursor
3749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003750 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003751 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3752 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003753 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003754 .build()));
3755
3756 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3757 WithSource(AINPUT_SOURCE_MOUSE)));
3758 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3759 WithSource(AINPUT_SOURCE_MOUSE)));
3760 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3761 WithSource(AINPUT_SOURCE_MOUSE)));
3762 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3763 WithSource(AINPUT_SOURCE_MOUSE)));
3764 // Touch down on the window
3765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003766 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003767 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3768 AINPUT_SOURCE_TOUCHSCREEN)
3769 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003770 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003771 .build()));
3772 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3773 WithSource(AINPUT_SOURCE_MOUSE)));
3774 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3775 WithSource(AINPUT_SOURCE_MOUSE)));
3776 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3777 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3778 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3779 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3780
3781 // pilfer the motion, retaining the gesture on the spy window.
3782 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3783 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3784 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3785
3786 // Touch UP on the window
3787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003788 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003789 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3790 AINPUT_SOURCE_TOUCHSCREEN)
3791 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003792 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003793 .build()));
3794 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3795 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3796
3797 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3798 // to send a new gesture. It should again go to both windows (spy and the window below), just
3799 // like the first gesture did, before pilfering. The window configuration has not changed.
3800
3801 // One more tap - DOWN
3802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003803 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003804 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3805 AINPUT_SOURCE_TOUCHSCREEN)
3806 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003807 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003808 .build()));
3809 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3810 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3811 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3812 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3813
3814 // Touch UP on the window
3815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003816 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003817 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3818 AINPUT_SOURCE_TOUCHSCREEN)
3819 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003820 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003821 .build()));
3822 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3823 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3824 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3825 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3826
3827 window->assertNoEvents();
3828 spyWindow->assertNoEvents();
3829}
3830
Garfield Tandf26e862020-07-01 20:18:19 -07003831// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3832// directly in this test.
3833TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003835 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003836 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003837 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003838
3839 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3840
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003841 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003842
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003844 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003845 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3846 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003847 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003848 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003849 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003850 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003852 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003853 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3854 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003855 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003856 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003857 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3858 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003859
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003861 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003862 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3863 AINPUT_SOURCE_MOUSE)
3864 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3865 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003866 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003867 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003868 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003869
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003871 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003872 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3873 AINPUT_SOURCE_MOUSE)
3874 .buttonState(0)
3875 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003876 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003877 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003878 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003879
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003881 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003882 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3883 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003884 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003885 .build()));
3886 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3887
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003888 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3889 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3890 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003891 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003892 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3893 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003894 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003895 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003896 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003897}
3898
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003899/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003900 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3901 * is generated.
3902 */
3903TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3905 sp<FakeWindowHandle> window =
3906 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3907 window->setFrame(Rect(0, 0, 1200, 800));
3908
3909 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3910
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003911 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003912
3913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003914 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003915 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3916 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003917 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003918 .build()));
3919 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3920
3921 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003922 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003923 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3924}
3925
3926/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003927 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3928 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003929TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
3930 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
3931 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07003932 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3933 sp<FakeWindowHandle> window =
3934 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3935 window->setFrame(Rect(0, 0, 1200, 800));
3936
3937 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3938
3939 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3940
3941 MotionEventBuilder hoverEnterBuilder =
3942 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3943 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3944 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3946 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3948 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3949 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3950 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3951}
3952
3953/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003954 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3955 */
3956TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3958 sp<FakeWindowHandle> window =
3959 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3960 window->setFrame(Rect(0, 0, 100, 100));
3961
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003962 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003963
3964 const int32_t mouseDeviceId = 7;
3965 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003966
3967 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3969 .deviceId(mouseDeviceId)
3970 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3971 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003972 window->consumeMotionEvent(
3973 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3974
3975 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3977 .deviceId(touchDeviceId)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3979 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003980
3981 window->consumeMotionEvent(
3982 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3983 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3984}
3985
3986/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003987 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003988 * The tap causes a HOVER_EXIT event to be generated because the current event
3989 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003990 */
3991TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3992 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3993 sp<FakeWindowHandle> window =
3994 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3995 window->setFrame(Rect(0, 0, 100, 100));
3996
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003997 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4000 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004001 ASSERT_NO_FATAL_FAILURE(
4002 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4003 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004004
4005 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4007 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4008 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004009 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004010 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4011 WithSource(AINPUT_SOURCE_MOUSE))));
4012
4013 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004014 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4015 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4016
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4018 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4019 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004020 ASSERT_NO_FATAL_FAILURE(
4021 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4022 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4023}
4024
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004025TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4027 sp<FakeWindowHandle> windowDefaultDisplay =
4028 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4029 ADISPLAY_ID_DEFAULT);
4030 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4031 sp<FakeWindowHandle> windowSecondDisplay =
4032 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4033 SECOND_DISPLAY_ID);
4034 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4035
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004036 mDispatcher->onWindowInfosChanged(
4037 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004038
4039 // Set cursor position in window in default display and check that hover enter and move
4040 // events are generated.
4041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004042 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004043 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4044 AINPUT_SOURCE_MOUSE)
4045 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004046 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004047 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004048 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004049
4050 // Remove all windows in secondary display and check that no event happens on window in
4051 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004052 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4053
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004054 windowDefaultDisplay->assertNoEvents();
4055
4056 // Move cursor position in window in default display and check that only hover move
4057 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004058 mDispatcher->onWindowInfosChanged(
4059 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004061 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004062 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4063 AINPUT_SOURCE_MOUSE)
4064 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004065 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004066 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004067 windowDefaultDisplay->consumeMotionEvent(
4068 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4069 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004070 windowDefaultDisplay->assertNoEvents();
4071}
4072
Garfield Tan00f511d2019-06-12 16:55:40 -07004073TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004075
4076 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004077 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004078 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004079 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004080 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004081 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004082
4083 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4084
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004085 mDispatcher->onWindowInfosChanged(
4086 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004087
4088 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4089 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004091 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004092 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004093 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004094 windowRight->assertNoEvents();
4095}
4096
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004097TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004099 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4100 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004101 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004102
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004103 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004104 setFocusedWindow(window);
4105
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004106 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004107
Prabir Pradhan678438e2023-04-13 19:32:51 +00004108 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004109
4110 // Window should receive key down event.
4111 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4112
4113 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4114 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004115 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004116 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004117 AKEY_EVENT_FLAG_CANCELED);
4118}
4119
4120TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004121 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004122 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4123 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004124
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004125 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004126
Prabir Pradhan678438e2023-04-13 19:32:51 +00004127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4128 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004129
4130 // Window should receive motion down event.
4131 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4132
4133 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4134 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004135 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004136 window->consumeMotionEvent(
4137 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004138}
4139
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004140TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4143 "Fake Window", ADISPLAY_ID_DEFAULT);
4144
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004145 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004146
4147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4148 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4149 .build());
4150
4151 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4152
4153 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4154 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4155 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4156
4157 // After the device has been reset, a new hovering stream can be sent to the window
4158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4159 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4160 .build());
4161 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4162}
4163
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004164TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004166 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4167 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004168 window->setFocusable(true);
4169
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004171 setFocusedWindow(window);
4172
4173 window->consumeFocusEvent(true);
4174
Prabir Pradhan678438e2023-04-13 19:32:51 +00004175 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004176 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4177 const nsecs_t injectTime = keyArgs.eventTime;
4178 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004179 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004180 // The dispatching time should be always greater than or equal to intercept key timeout.
4181 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4182 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4183 std::chrono::nanoseconds(interceptKeyTimeout).count());
4184}
4185
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004186/**
4187 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4188 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004189TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004191 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4192 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004193 window->setFocusable(true);
4194
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004195 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004196 setFocusedWindow(window);
4197
4198 window->consumeFocusEvent(true);
4199
Prabir Pradhan678438e2023-04-13 19:32:51 +00004200 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004201 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004202
4203 // Set a value that's significantly larger than the default consumption timeout. If the
4204 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4205 mFakePolicy->setInterceptKeyTimeout(600ms);
4206 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4207 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004208 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4209}
4210
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004211/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004212 * Two windows. First is a regular window. Second does not overlap with the first, and has
4213 * WATCH_OUTSIDE_TOUCH.
4214 * Both windows are owned by the same UID.
4215 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4216 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4217 */
4218TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004220 sp<FakeWindowHandle> window =
4221 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004222 window->setFrame(Rect{0, 0, 100, 100});
4223
4224 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004225 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004226 ADISPLAY_ID_DEFAULT);
4227 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4228 outsideWindow->setWatchOutsideTouch(true);
4229 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004230 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004231
4232 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004233 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4234 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4235 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004236 window->consumeMotionDown();
4237 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4238 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4239 outsideWindow->consumeMotionEvent(
4240 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4241}
4242
4243/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004244 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4245 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4246 * ACTION_OUTSIDE event is sent per gesture.
4247 */
4248TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4249 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4250 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004251 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4252 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004253 window->setWatchOutsideTouch(true);
4254 window->setFrame(Rect{0, 0, 100, 100});
4255 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004256 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4257 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004258 secondWindow->setFrame(Rect{100, 100, 200, 200});
4259 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004260 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4261 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004262 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004263 mDispatcher->onWindowInfosChanged(
4264 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004265
4266 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004267 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4268 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4269 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004270 window->assertNoEvents();
4271 secondWindow->assertNoEvents();
4272
4273 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4274 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004275 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4276 ADISPLAY_ID_DEFAULT,
4277 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004278 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4279 window->consumeMotionEvent(
4280 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004281 secondWindow->consumeMotionDown();
4282 thirdWindow->assertNoEvents();
4283
4284 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4285 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004286 mDispatcher->notifyMotion(
4287 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4288 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004289 window->assertNoEvents();
4290 secondWindow->consumeMotionMove();
4291 thirdWindow->consumeMotionDown();
4292}
4293
Prabir Pradhan814fe082022-07-22 20:22:18 +00004294TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4295 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004296 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4297 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004298 window->setFocusable(true);
4299
Patrick Williamsd828f302023-04-28 17:52:08 -05004300 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004301 setFocusedWindow(window);
4302
4303 window->consumeFocusEvent(true);
4304
Prabir Pradhan678438e2023-04-13 19:32:51 +00004305 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4306 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4307 mDispatcher->notifyKey(keyDown);
4308 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004309
4310 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4311 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4312
4313 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004314 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004315
4316 window->consumeFocusEvent(false);
4317
Prabir Pradhan678438e2023-04-13 19:32:51 +00004318 mDispatcher->notifyKey(keyDown);
4319 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004320 window->assertNoEvents();
4321}
4322
Arthur Hung96483742022-11-15 03:30:48 +00004323TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4325 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4326 "Fake Window", ADISPLAY_ID_DEFAULT);
4327 // Ensure window is non-split and have some transform.
4328 window->setPreventSplitting(true);
4329 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004330 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004331
4332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004333 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004334 {50, 50}))
4335 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4336 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4337
4338 const MotionEvent secondFingerDownEvent =
4339 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4340 .displayId(ADISPLAY_ID_DEFAULT)
4341 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004342 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4343 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004344 .build();
4345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004346 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004347 InputEventInjectionSync::WAIT_FOR_RESULT))
4348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4349
4350 const MotionEvent* event = window->consumeMotion();
4351 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4352 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4353 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4354 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4355 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4356}
4357
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004358/**
4359 * Two windows: a splittable and a non-splittable.
4360 * The non-splittable window shouldn't receive any "incomplete" gestures.
4361 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4362 * The second pointer should be dropped because the initial window is splittable, so it won't get
4363 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4364 * "incomplete" gestures.
4365 */
4366TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4368 sp<FakeWindowHandle> leftWindow =
4369 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4370 ADISPLAY_ID_DEFAULT);
4371 leftWindow->setPreventSplitting(false);
4372 leftWindow->setFrame(Rect(0, 0, 100, 100));
4373 sp<FakeWindowHandle> rightWindow =
4374 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4375 ADISPLAY_ID_DEFAULT);
4376 rightWindow->setPreventSplitting(true);
4377 rightWindow->setFrame(Rect(100, 100, 200, 200));
4378 mDispatcher->onWindowInfosChanged(
4379 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4380
4381 // Touch down on left, splittable window
4382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4383 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4384 .build());
4385 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4386
4387 mDispatcher->notifyMotion(
4388 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4389 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4390 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4391 .build());
4392 leftWindow->assertNoEvents();
4393 rightWindow->assertNoEvents();
4394}
4395
Harry Cuttsb166c002023-05-09 13:06:05 +00004396TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4398 sp<FakeWindowHandle> window =
4399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4400 window->setFrame(Rect(0, 0, 400, 400));
4401 sp<FakeWindowHandle> trustedOverlay =
4402 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4403 ADISPLAY_ID_DEFAULT);
4404 trustedOverlay->setSpy(true);
4405 trustedOverlay->setTrustedOverlay(true);
4406
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004407 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004408
4409 // Start a three-finger touchpad swipe
4410 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4411 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4412 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4413 .build());
4414 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4415 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4416 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4417 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4418 .build());
4419 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4420 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4421 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4422 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4423 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4424 .build());
4425
4426 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4427 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4428 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4429
4430 // Move the swipe a bit
4431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4432 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4433 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4434 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4435 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4436 .build());
4437
4438 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4439
4440 // End the swipe
4441 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4442 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4443 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4444 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4445 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4446 .build());
4447 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4448 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4449 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4450 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4451 .build());
4452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4453 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4454 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4455 .build());
4456
4457 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4458 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4459 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4460
4461 window->assertNoEvents();
4462}
4463
4464TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4466 sp<FakeWindowHandle> window =
4467 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4468 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004470
4471 // Start a three-finger touchpad swipe
4472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4473 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4474 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4475 .build());
4476 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4477 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4478 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4479 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4480 .build());
4481 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4482 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4483 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4484 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4485 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4486 .build());
4487
4488 // Move the swipe a bit
4489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4490 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4491 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4492 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4493 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4494 .build());
4495
4496 // End the swipe
4497 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4498 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4499 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4500 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4501 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4502 .build());
4503 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4504 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4505 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4506 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4507 .build());
4508 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4509 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4510 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4511 .build());
4512
4513 window->assertNoEvents();
4514}
4515
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004516/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004517 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4518 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004519 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004520 */
4521TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4522 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4523 sp<FakeWindowHandle> window =
4524 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4525 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004526 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004527
4528 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4530 .downTime(baseTime + 10)
4531 .eventTime(baseTime + 10)
4532 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4533 .build());
4534
4535 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4536
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004537 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004538 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004539
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004540 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004541
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004542 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4543 .downTime(baseTime + 10)
4544 .eventTime(baseTime + 30)
4545 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4546 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4547 .build());
4548
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004549 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4550
4551 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004552 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4553 .downTime(baseTime + 10)
4554 .eventTime(baseTime + 40)
4555 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4556 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4557 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004558
4559 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4560
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4562 .downTime(baseTime + 10)
4563 .eventTime(baseTime + 50)
4564 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4565 .build());
4566
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004567 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4568
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4570 .downTime(baseTime + 60)
4571 .eventTime(baseTime + 60)
4572 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4573 .build());
4574
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004575 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004576}
4577
4578/**
Hu Guo771a7692023-09-17 20:51:08 +08004579 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4580 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4581 * its coordinates should be converted by the transform of the windows of target screen.
4582 */
4583TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4584 // This case will create a window and a spy window on the default display and mirror
4585 // window on the second display. cancel event is sent through spy window pilferPointers
4586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4587
4588 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4589 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4590 spyWindowDefaultDisplay->setTrustedOverlay(true);
4591 spyWindowDefaultDisplay->setSpy(true);
4592
4593 sp<FakeWindowHandle> windowDefaultDisplay =
4594 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4595 ADISPLAY_ID_DEFAULT);
4596 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4597
4598 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4599 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4600
4601 // Add the windows to the dispatcher
4602 mDispatcher->onWindowInfosChanged(
4603 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4604 *windowSecondDisplay->getInfo()},
4605 {},
4606 0,
4607 0});
4608
4609 // Send down to ADISPLAY_ID_DEFAULT
4610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4611 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4612 {100, 100}))
4613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4614
4615 spyWindowDefaultDisplay->consumeMotionDown();
4616 windowDefaultDisplay->consumeMotionDown();
4617
4618 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4619
4620 // windowDefaultDisplay gets cancel
4621 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4622 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4623
4624 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4625 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4626 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4627 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4628 EXPECT_EQ(100, event->getX(0));
4629 EXPECT_EQ(100, event->getY(0));
4630}
4631
4632/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004633 * Ensure the correct coordinate spaces are used by InputDispatcher.
4634 *
4635 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4636 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4637 * space.
4638 */
4639class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4640public:
4641 void SetUp() override {
4642 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004643 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004644 }
4645
4646 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4647 gui::DisplayInfo info;
4648 info.displayId = displayId;
4649 info.transform = transform;
4650 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004651 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004652 }
4653
4654 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4655 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004656 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004657 }
4658
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004659 void removeAllWindowsAndDisplays() {
4660 mDisplayInfos.clear();
4661 mWindowInfos.clear();
4662 }
4663
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004664 // Set up a test scenario where the display has a scaled projection and there are two windows
4665 // on the display.
4666 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4667 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4668 // respectively.
4669 ui::Transform displayTransform;
4670 displayTransform.set(2, 0, 0, 4);
4671 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4672
4673 std::shared_ptr<FakeApplicationHandle> application =
4674 std::make_shared<FakeApplicationHandle>();
4675
4676 // Add two windows to the display. Their frames are represented in the display space.
4677 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004678 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4679 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004680 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4681 addWindow(firstWindow);
4682
4683 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004684 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4685 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004686 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4687 addWindow(secondWindow);
4688 return {std::move(firstWindow), std::move(secondWindow)};
4689 }
4690
4691private:
4692 std::vector<gui::DisplayInfo> mDisplayInfos;
4693 std::vector<gui::WindowInfo> mWindowInfos;
4694};
4695
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004696TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004697 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4698 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004699 // selected so that if the hit test was performed with the point and the bounds being in
4700 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004701 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4702 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4703 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004704
4705 firstWindow->consumeMotionDown();
4706 secondWindow->assertNoEvents();
4707}
4708
4709// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4710// the event should be treated as being in the logical display space.
4711TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4712 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4713 // Send down to the first window. The point is represented in the logical display space. The
4714 // point is selected so that if the hit test was done in logical display space, then it would
4715 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004716 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004717 PointF{75 * 2, 55 * 4});
4718
4719 firstWindow->consumeMotionDown();
4720 secondWindow->assertNoEvents();
4721}
4722
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004723// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4724// event should be treated as being in the logical display space.
4725TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4726 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4727
4728 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4729 ui::Transform injectedEventTransform;
4730 injectedEventTransform.set(matrix);
4731 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4732 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4733
4734 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4735 .displayId(ADISPLAY_ID_DEFAULT)
4736 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004737 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004738 .x(untransformedPoint.x)
4739 .y(untransformedPoint.y))
4740 .build();
4741 event.transform(matrix);
4742
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004743 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004744 InputEventInjectionSync::WAIT_FOR_RESULT);
4745
4746 firstWindow->consumeMotionDown();
4747 secondWindow->assertNoEvents();
4748}
4749
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004750TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4751 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4752
4753 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004754 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4755 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4756 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004757
4758 firstWindow->assertNoEvents();
4759 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004760 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004761 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4762
4763 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4764 EXPECT_EQ(300, event->getRawX(0));
4765 EXPECT_EQ(880, event->getRawY(0));
4766
4767 // Ensure that the x and y values are in the window's coordinate space.
4768 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4769 // the logical display space. This will be the origin of the window space.
4770 EXPECT_EQ(100, event->getX(0));
4771 EXPECT_EQ(80, event->getY(0));
4772}
4773
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004774TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4775 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4776 // The monitor will always receive events in the logical display's coordinate space, because
4777 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004778 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004779
4780 // Send down to the first window.
4781 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4782 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4783 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4784 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4785
4786 // Second pointer goes down on second window.
4787 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4788 ADISPLAY_ID_DEFAULT,
4789 {PointF{50, 100}, PointF{150, 220}}));
4790 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4791 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4792 {1, PointF{300, 880}}};
4793 monitor.consumeMotionEvent(
4794 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4795
4796 mDispatcher->cancelCurrentTouch();
4797
4798 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4799 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4800 monitor.consumeMotionEvent(
4801 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4802}
4803
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004804TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4805 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4806
4807 // Send down to the first window.
4808 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4809 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4810 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4811
4812 // The pointer is transferred to the second window, and the second window receives it in the
4813 // correct coordinate space.
4814 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4815 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4816 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4817}
4818
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004819TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4820 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4821
4822 // Send hover move to the second window, and ensure it shows up as hover enter.
4823 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4824 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4825 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4826 WithCoords(100, 80), WithRawCoords(300, 880)));
4827
4828 // Touch down at the same location and ensure a hover exit is synthesized.
4829 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4830 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4831 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4832 WithRawCoords(300, 880)));
4833 secondWindow->consumeMotionEvent(
4834 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4835 secondWindow->assertNoEvents();
4836 firstWindow->assertNoEvents();
4837}
4838
Prabir Pradhan453ae732023-10-13 14:30:14 +00004839// Same as above, but while the window is being mirrored.
4840TEST_F(InputDispatcherDisplayProjectionTest,
4841 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4842 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4843
4844 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4845 ui::Transform secondDisplayTransform;
4846 secondDisplayTransform.set(matrix);
4847 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4848
4849 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4850 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4851 addWindow(secondWindowClone);
4852
4853 // Send hover move to the second window, and ensure it shows up as hover enter.
4854 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4855 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4856 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4857 WithCoords(100, 80), WithRawCoords(300, 880)));
4858
4859 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4860 // display.
4861 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4862 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4863 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4864 WithRawCoords(300, 880)));
4865 secondWindow->consumeMotionEvent(
4866 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4867 secondWindow->assertNoEvents();
4868 firstWindow->assertNoEvents();
4869}
4870
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004871TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4872 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4873
4874 // Send hover enter to second window
4875 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4876 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4877 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4878 WithCoords(100, 80), WithRawCoords(300, 880)));
4879
4880 mDispatcher->cancelCurrentTouch();
4881
4882 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4883 WithRawCoords(300, 880)));
4884 secondWindow->assertNoEvents();
4885 firstWindow->assertNoEvents();
4886}
4887
Prabir Pradhan453ae732023-10-13 14:30:14 +00004888// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004889TEST_F(InputDispatcherDisplayProjectionTest,
4890 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4891 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4892
4893 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4894 ui::Transform secondDisplayTransform;
4895 secondDisplayTransform.set(matrix);
4896 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4897
4898 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4899 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4900 addWindow(secondWindowClone);
4901
4902 // Send hover enter to second window
4903 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4904 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4905 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4906 WithCoords(100, 80), WithRawCoords(300, 880),
4907 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4908
4909 mDispatcher->cancelCurrentTouch();
4910
4911 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4912 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4913 WithRawCoords(300, 880),
4914 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4915 secondWindow->assertNoEvents();
4916 firstWindow->assertNoEvents();
4917}
4918
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004919/** Ensure consistent behavior of InputDispatcher in all orientations. */
4920class InputDispatcherDisplayOrientationFixture
4921 : public InputDispatcherDisplayProjectionTest,
4922 public ::testing::WithParamInterface<ui::Rotation> {};
4923
4924// This test verifies the touchable region of a window for all rotations of the display by tapping
4925// in different locations on the display, specifically points close to the four corners of a
4926// window.
4927TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4928 constexpr static int32_t displayWidth = 400;
4929 constexpr static int32_t displayHeight = 800;
4930
4931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4932
4933 const auto rotation = GetParam();
4934
4935 // Set up the display with the specified rotation.
4936 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4937 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4938 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4939 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4940 logicalDisplayWidth, logicalDisplayHeight);
4941 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4942
4943 // Create a window with its bounds determined in the logical display.
4944 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4945 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4946 sp<FakeWindowHandle> window =
4947 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4948 window->setFrame(frameInDisplay, displayTransform);
4949 addWindow(window);
4950
4951 // The following points in logical display space should be inside the window.
4952 static const std::array<vec2, 4> insidePoints{
4953 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4954 for (const auto pointInsideWindow : insidePoints) {
4955 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4956 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004957 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4958 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4959 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004960 window->consumeMotionDown();
4961
Prabir Pradhan678438e2023-04-13 19:32:51 +00004962 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4963 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4964 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004965 window->consumeMotionUp();
4966 }
4967
4968 // The following points in logical display space should be outside the window.
4969 static const std::array<vec2, 5> outsidePoints{
4970 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4971 for (const auto pointOutsideWindow : outsidePoints) {
4972 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4973 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004974 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4975 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4976 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004977
Prabir Pradhan678438e2023-04-13 19:32:51 +00004978 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4979 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4980 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004981 }
4982 window->assertNoEvents();
4983}
4984
4985// Run the precision tests for all rotations.
4986INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4987 InputDispatcherDisplayOrientationFixture,
4988 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4989 ui::ROTATION_270),
4990 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4991 return ftl::enum_string(testParamInfo.param);
4992 });
4993
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004994using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4995 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004996
4997class TransferTouchFixture : public InputDispatcherTest,
4998 public ::testing::WithParamInterface<TransferFunction> {};
4999
5000TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005002
5003 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005004 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005005 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5006 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005007 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005008 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005009 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5010 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005011 sp<FakeWindowHandle> wallpaper =
5012 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5013 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005014 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005015 mDispatcher->onWindowInfosChanged(
5016 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005017
5018 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005019 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5020 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005021
Svet Ganov5d3bc372020-01-26 23:11:07 -08005022 // Only the first window should get the down event
5023 firstWindow->consumeMotionDown();
5024 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005025 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005026
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005027 // Transfer touch to the second window
5028 TransferFunction f = GetParam();
5029 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5030 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005031 // The first window gets cancel and the second gets down
5032 firstWindow->consumeMotionCancel();
5033 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005034 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005035
5036 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005037 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5038 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005039 // The first window gets no events and the second gets up
5040 firstWindow->assertNoEvents();
5041 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005042 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005043}
5044
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005045/**
5046 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5047 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5048 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5049 * natural to the user.
5050 * In this test, we are sending a pointer to both spy window and first window. We then try to
5051 * transfer touch to the second window. The dispatcher should identify the first window as the
5052 * one that should lose the gesture, and therefore the action should be to move the gesture from
5053 * the first window to the second.
5054 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5055 * the other API, as well.
5056 */
5057TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5059
5060 // Create a couple of windows + a spy window
5061 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005062 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005063 spyWindow->setTrustedOverlay(true);
5064 spyWindow->setSpy(true);
5065 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005066 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005067 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005068 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005069
5070 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005071 mDispatcher->onWindowInfosChanged(
5072 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005073
5074 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005075 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5076 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005077 // Only the first window and spy should get the down event
5078 spyWindow->consumeMotionDown();
5079 firstWindow->consumeMotionDown();
5080
5081 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5082 // if f === 'transferTouch'.
5083 TransferFunction f = GetParam();
5084 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5085 ASSERT_TRUE(success);
5086 // The first window gets cancel and the second gets down
5087 firstWindow->consumeMotionCancel();
5088 secondWindow->consumeMotionDown();
5089
5090 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005091 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5092 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005093 // The first window gets no events and the second+spy get up
5094 firstWindow->assertNoEvents();
5095 spyWindow->consumeMotionUp();
5096 secondWindow->consumeMotionUp();
5097}
5098
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005099TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005101
5102 PointF touchPoint = {10, 10};
5103
5104 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005105 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005106 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5107 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005108 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005109 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005110 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5111 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005112 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005113
5114 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005115 mDispatcher->onWindowInfosChanged(
5116 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005117
5118 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005119 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5120 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5121 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005122 // Only the first window should get the down event
5123 firstWindow->consumeMotionDown();
5124 secondWindow->assertNoEvents();
5125
5126 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005127 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5128 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005129 // Only the first window should get the pointer down event
5130 firstWindow->consumeMotionPointerDown(1);
5131 secondWindow->assertNoEvents();
5132
5133 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005134 TransferFunction f = GetParam();
5135 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5136 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005137 // The first window gets cancel and the second gets down and pointer down
5138 firstWindow->consumeMotionCancel();
5139 secondWindow->consumeMotionDown();
5140 secondWindow->consumeMotionPointerDown(1);
5141
5142 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005143 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5144 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005145 // The first window gets nothing and the second gets pointer up
5146 firstWindow->assertNoEvents();
5147 secondWindow->consumeMotionPointerUp(1);
5148
5149 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005150 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5151 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005152 // The first window gets nothing and the second gets up
5153 firstWindow->assertNoEvents();
5154 secondWindow->consumeMotionUp();
5155}
5156
Arthur Hungc539dbb2022-12-08 07:45:36 +00005157TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5159
5160 // Create a couple of windows
5161 sp<FakeWindowHandle> firstWindow =
5162 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5163 ADISPLAY_ID_DEFAULT);
5164 firstWindow->setDupTouchToWallpaper(true);
5165 sp<FakeWindowHandle> secondWindow =
5166 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5167 ADISPLAY_ID_DEFAULT);
5168 secondWindow->setDupTouchToWallpaper(true);
5169
5170 sp<FakeWindowHandle> wallpaper1 =
5171 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5172 wallpaper1->setIsWallpaper(true);
5173
5174 sp<FakeWindowHandle> wallpaper2 =
5175 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5176 wallpaper2->setIsWallpaper(true);
5177 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005178 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5179 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5180 {},
5181 0,
5182 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005183
5184 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005185 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5186 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005187
5188 // Only the first window should get the down event
5189 firstWindow->consumeMotionDown();
5190 secondWindow->assertNoEvents();
5191 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5192 wallpaper2->assertNoEvents();
5193
5194 // Transfer touch focus to the second window
5195 TransferFunction f = GetParam();
5196 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5197 ASSERT_TRUE(success);
5198
5199 // The first window gets cancel and the second gets down
5200 firstWindow->consumeMotionCancel();
5201 secondWindow->consumeMotionDown();
5202 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5203 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5204
5205 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005206 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5207 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005208 // The first window gets no events and the second gets up
5209 firstWindow->assertNoEvents();
5210 secondWindow->consumeMotionUp();
5211 wallpaper1->assertNoEvents();
5212 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5213}
5214
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005215// For the cases of single pointer touch and two pointers non-split touch, the api's
5216// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5217// for the case where there are multiple pointers split across several windows.
5218INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5219 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005220 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5221 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005222 return dispatcher->transferTouch(destChannelToken,
5223 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005224 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005225 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5226 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005227 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005228 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005229 }));
5230
Svet Ganov5d3bc372020-01-26 23:11:07 -08005231TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005233
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005234 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005235 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5236 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005237 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005238
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005239 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005240 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5241 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005242 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005243
5244 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005245 mDispatcher->onWindowInfosChanged(
5246 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005247
5248 PointF pointInFirst = {300, 200};
5249 PointF pointInSecond = {300, 600};
5250
5251 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005252 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5253 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5254 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005255 // Only the first window should get the down event
5256 firstWindow->consumeMotionDown();
5257 secondWindow->assertNoEvents();
5258
5259 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005260 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5261 ADISPLAY_ID_DEFAULT,
5262 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005263 // The first window gets a move and the second a down
5264 firstWindow->consumeMotionMove();
5265 secondWindow->consumeMotionDown();
5266
5267 // Transfer touch focus to the second window
5268 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5269 // The first window gets cancel and the new gets pointer down (it already saw down)
5270 firstWindow->consumeMotionCancel();
5271 secondWindow->consumeMotionPointerDown(1);
5272
5273 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005274 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5275 ADISPLAY_ID_DEFAULT,
5276 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005277 // The first window gets nothing and the second gets pointer up
5278 firstWindow->assertNoEvents();
5279 secondWindow->consumeMotionPointerUp(1);
5280
5281 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005282 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5283 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005284 // The first window gets nothing and the second gets up
5285 firstWindow->assertNoEvents();
5286 secondWindow->consumeMotionUp();
5287}
5288
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005289// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5290// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5291// touch is not supported, so the touch should continue on those windows and the transferred-to
5292// window should get nothing.
5293TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5295
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005296 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005297 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5298 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005299 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005300
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005301 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005302 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5303 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005304 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005305
5306 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005307 mDispatcher->onWindowInfosChanged(
5308 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005309
5310 PointF pointInFirst = {300, 200};
5311 PointF pointInSecond = {300, 600};
5312
5313 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005314 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5315 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5316 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005317 // Only the first window should get the down event
5318 firstWindow->consumeMotionDown();
5319 secondWindow->assertNoEvents();
5320
5321 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005322 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5323 ADISPLAY_ID_DEFAULT,
5324 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005325 // The first window gets a move and the second a down
5326 firstWindow->consumeMotionMove();
5327 secondWindow->consumeMotionDown();
5328
5329 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005330 const bool transferred =
5331 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005332 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5333 ASSERT_FALSE(transferred);
5334 firstWindow->assertNoEvents();
5335 secondWindow->assertNoEvents();
5336
5337 // The rest of the dispatch should proceed as normal
5338 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005339 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5340 ADISPLAY_ID_DEFAULT,
5341 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005342 // The first window gets MOVE and the second gets pointer up
5343 firstWindow->consumeMotionMove();
5344 secondWindow->consumeMotionUp();
5345
5346 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005347 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5348 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005349 // The first window gets nothing and the second gets up
5350 firstWindow->consumeMotionUp();
5351 secondWindow->assertNoEvents();
5352}
5353
Arthur Hungabbb9d82021-09-01 14:52:30 +00005354// This case will create two windows and one mirrored window on the default display and mirror
5355// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5356// the windows info of second display before default display.
5357TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5359 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005360 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005361 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005362 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005363 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005364 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005365
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005366 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005367 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005368
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005369 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005370 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005371
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005372 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005373 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005374
5375 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005376 mDispatcher->onWindowInfosChanged(
5377 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5378 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5379 *secondWindowInPrimary->getInfo()},
5380 {},
5381 0,
5382 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005383
5384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005385 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005386 {50, 50}))
5387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5388
5389 // Window should receive motion event.
5390 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5391
5392 // Transfer touch focus
5393 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5394 secondWindowInPrimary->getToken()));
5395 // The first window gets cancel.
5396 firstWindowInPrimary->consumeMotionCancel();
5397 secondWindowInPrimary->consumeMotionDown();
5398
5399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005400 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005401 ADISPLAY_ID_DEFAULT, {150, 50}))
5402 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5403 firstWindowInPrimary->assertNoEvents();
5404 secondWindowInPrimary->consumeMotionMove();
5405
5406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005407 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005408 {150, 50}))
5409 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5410 firstWindowInPrimary->assertNoEvents();
5411 secondWindowInPrimary->consumeMotionUp();
5412}
5413
5414// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5415// 'transferTouch' api.
5416TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5417 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5418 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005419 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005420 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005421 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005422 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005423 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005424
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005425 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005426 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005427
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005428 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005429 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005430
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005431 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005432 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005433
5434 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005435 mDispatcher->onWindowInfosChanged(
5436 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5437 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5438 *secondWindowInPrimary->getInfo()},
5439 {},
5440 0,
5441 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005442
5443 // Touch on second display.
5444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005445 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5446 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005447 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5448
5449 // Window should receive motion event.
5450 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5451
5452 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005453 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005454
5455 // The first window gets cancel.
5456 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5457 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5458
5459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005460 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005461 SECOND_DISPLAY_ID, {150, 50}))
5462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5463 firstWindowInPrimary->assertNoEvents();
5464 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5465
5466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005467 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5469 firstWindowInPrimary->assertNoEvents();
5470 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5471}
5472
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005473TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005475 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5476 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005477
Vishnu Nair47074b82020-08-14 11:54:47 -07005478 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005479 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005480 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005481
5482 window->consumeFocusEvent(true);
5483
Prabir Pradhan678438e2023-04-13 19:32:51 +00005484 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005485
5486 // Window should receive key down event.
5487 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005488
5489 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005490 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005491 mFakePolicy->assertUserActivityPoked();
5492}
5493
5494TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5496 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5497 "Fake Window", ADISPLAY_ID_DEFAULT);
5498
5499 window->setDisableUserActivity(true);
5500 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005501 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005502 setFocusedWindow(window);
5503
5504 window->consumeFocusEvent(true);
5505
5506 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5507
5508 // Window should receive key down event.
5509 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5510
5511 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005512 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005513 mFakePolicy->assertUserActivityNotPoked();
5514}
5515
5516TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5518 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5519 "Fake Window", ADISPLAY_ID_DEFAULT);
5520
5521 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005522 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005523 setFocusedWindow(window);
5524
5525 window->consumeFocusEvent(true);
5526
5527 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5528 mDispatcher->waitForIdle();
5529
5530 // System key is not passed down
5531 window->assertNoEvents();
5532
5533 // Should have poked user activity
5534 mFakePolicy->assertUserActivityPoked();
5535}
5536
5537TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5538 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5539 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5540 "Fake Window", ADISPLAY_ID_DEFAULT);
5541
5542 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005543 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005544 setFocusedWindow(window);
5545
5546 window->consumeFocusEvent(true);
5547
5548 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5549 mDispatcher->waitForIdle();
5550
5551 // System key is not passed down
5552 window->assertNoEvents();
5553
5554 // Should have poked user activity
5555 mFakePolicy->assertUserActivityPoked();
5556}
5557
5558TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5560 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5561 "Fake Window", ADISPLAY_ID_DEFAULT);
5562
5563 window->setDisableUserActivity(true);
5564 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005565 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005566 setFocusedWindow(window);
5567
5568 window->consumeFocusEvent(true);
5569
5570 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5571 mDispatcher->waitForIdle();
5572
5573 // System key is not passed down
5574 window->assertNoEvents();
5575
5576 // Should have poked user activity
5577 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005578}
5579
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005580TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5581 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5582 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5583 "Fake Window", ADISPLAY_ID_DEFAULT);
5584
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005585 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005586
5587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005588 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005589 ADISPLAY_ID_DEFAULT, {100, 100}))
5590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5591
5592 window->consumeMotionEvent(
5593 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5594
5595 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005596 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005597 mFakePolicy->assertUserActivityPoked();
5598}
5599
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005600TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005602 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5603 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005605 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005606
Prabir Pradhan678438e2023-04-13 19:32:51 +00005607 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005608 mDispatcher->waitForIdle();
5609
5610 window->assertNoEvents();
5611}
5612
5613// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5614TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005616 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5617 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005618
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005619 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005620
5621 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005622 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005623 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005624 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5625 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005626
5627 // Window should receive only the motion event
5628 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5629 window->assertNoEvents(); // Key event or focus event will not be received
5630}
5631
arthurhungea3f4fc2020-12-21 23:18:53 +08005632TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5633 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5634
arthurhungea3f4fc2020-12-21 23:18:53 +08005635 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005636 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5637 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005638 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005639
arthurhungea3f4fc2020-12-21 23:18:53 +08005640 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005641 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5642 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005643 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005644
5645 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005646 mDispatcher->onWindowInfosChanged(
5647 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005648
5649 PointF pointInFirst = {300, 200};
5650 PointF pointInSecond = {300, 600};
5651
5652 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005653 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5654 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5655 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005656 // Only the first window should get the down event
5657 firstWindow->consumeMotionDown();
5658 secondWindow->assertNoEvents();
5659
5660 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005661 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5662 ADISPLAY_ID_DEFAULT,
5663 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005664 // The first window gets a move and the second a down
5665 firstWindow->consumeMotionMove();
5666 secondWindow->consumeMotionDown();
5667
5668 // Send pointer cancel to the second window
5669 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005670 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005671 {pointInFirst, pointInSecond});
5672 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005673 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005674 // The first window gets move and the second gets cancel.
5675 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5676 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5677
5678 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005679 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5680 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005681 // The first window gets up and the second gets nothing.
5682 firstWindow->consumeMotionUp();
5683 secondWindow->assertNoEvents();
5684}
5685
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005686TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5688
5689 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005690 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005691 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005692 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5693 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5694 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5695
Harry Cutts33476232023-01-30 19:57:29 +00005696 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005697 window->assertNoEvents();
5698 mDispatcher->waitForIdle();
5699}
5700
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005701using InputDispatcherMonitorTest = InputDispatcherTest;
5702
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005703/**
5704 * Two entities that receive touch: A window, and a global monitor.
5705 * The touch goes to the window, and then the window disappears.
5706 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5707 * for the monitor, as well.
5708 * 1. foregroundWindow
5709 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5710 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005711TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5713 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005714 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005715
Prabir Pradhanfb549072023-10-05 19:17:36 +00005716 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005721 {100, 200}))
5722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5723
5724 // Both the foreground window and the global monitor should receive the touch down
5725 window->consumeMotionDown();
5726 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5727
5728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005729 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005730 ADISPLAY_ID_DEFAULT, {110, 200}))
5731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5732
5733 window->consumeMotionMove();
5734 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5735
5736 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005737 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005738 window->consumeMotionCancel();
5739 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5740
5741 // If more events come in, there will be no more foreground window to send them to. This will
5742 // cause a cancel for the monitor, as well.
5743 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005744 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005745 ADISPLAY_ID_DEFAULT, {120, 200}))
5746 << "Injection should fail because the window was removed";
5747 window->assertNoEvents();
5748 // Global monitor now gets the cancel
5749 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5750}
5751
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005752TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5755 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005756 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005757
Prabir Pradhanfb549072023-10-05 19:17:36 +00005758 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005759
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005761 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005763 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005764 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005765}
5766
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005767TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005768 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005769
Chris Yea209fde2020-07-22 13:54:51 -07005770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005771 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5772 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005773 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005774
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005776 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005778 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005779 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005780
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005781 // Pilfer pointers from the monitor.
5782 // This should not do anything and the window should continue to receive events.
5783 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005784
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005786 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005787 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005789
5790 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5791 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005792}
5793
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005794TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5797 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005799 window->setWindowOffset(20, 40);
5800 window->setWindowTransform(0, 1, -1, 0);
5801
Prabir Pradhanfb549072023-10-05 19:17:36 +00005802 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005803
5804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005805 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5807 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5808 MotionEvent* event = monitor.consumeMotion();
5809 // Even though window has transform, gesture monitor must not.
5810 ASSERT_EQ(ui::Transform(), event->getTransform());
5811}
5812
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005813TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005815 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005816
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005817 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005818 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005819 << "Injection should fail if there is a monitor, but no touchable window";
5820 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005821}
5822
chaviw81e2bb92019-12-18 15:03:51 -08005823TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005824 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005825 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5826 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005827
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005828 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005829
5830 NotifyMotionArgs motionArgs =
5831 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5832 ADISPLAY_ID_DEFAULT);
5833
Prabir Pradhan678438e2023-04-13 19:32:51 +00005834 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005835 // Window should receive motion down event.
5836 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5837
5838 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005839 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005840 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5841 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5842 motionArgs.pointerCoords[0].getX() - 10);
5843
Prabir Pradhan678438e2023-04-13 19:32:51 +00005844 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005845 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005846 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005847}
5848
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005849/**
5850 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5851 * the device default right away. In the test scenario, we check both the default value,
5852 * and the action of enabling / disabling.
5853 */
5854TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005856 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5857 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005858 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005859
5860 // Set focused application.
5861 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005862 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005863
5864 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005865 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005866 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005867 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005868
5869 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005870 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005872 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005873
5874 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005875 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005876 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005877 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005878 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005879 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005880 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005881 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005882
5883 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005884 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005885 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005886 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005887
5888 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005889 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005890 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005891 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005892 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005893 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005894 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005895 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005896
5897 window->assertNoEvents();
5898}
5899
Gang Wange9087892020-01-07 12:17:14 -05005900TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005902 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5903 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005904
5905 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005906 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005907
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005908 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005909 setFocusedWindow(window);
5910
Harry Cutts33476232023-01-30 19:57:29 +00005911 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005912
Prabir Pradhan678438e2023-04-13 19:32:51 +00005913 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5914 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005915
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005916 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005917 ASSERT_NE(event, nullptr);
5918
5919 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5920 ASSERT_NE(verified, nullptr);
5921 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5922
5923 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5924 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5925 ASSERT_EQ(keyArgs.source, verified->source);
5926 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5927
5928 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5929
5930 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005931 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005932 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005933 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5934 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5935 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5936 ASSERT_EQ(0, verifiedKey.repeatCount);
5937}
5938
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005939TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005941 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5942 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005943
5944 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5945
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005946 ui::Transform transform;
5947 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5948
5949 gui::DisplayInfo displayInfo;
5950 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5951 displayInfo.transform = transform;
5952
Patrick Williamsd828f302023-04-28 17:52:08 -05005953 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005954
Prabir Pradhan678438e2023-04-13 19:32:51 +00005955 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005956 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5957 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005958 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005959
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005960 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005961 ASSERT_NE(event, nullptr);
5962
5963 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5964 ASSERT_NE(verified, nullptr);
5965 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5966
5967 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5968 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5969 EXPECT_EQ(motionArgs.source, verified->source);
5970 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5971
5972 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5973
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005974 const vec2 rawXY =
5975 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5976 motionArgs.pointerCoords[0].getXYValue());
5977 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5978 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005979 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005980 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005981 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005982 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5983 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5984}
5985
chaviw09c8d2d2020-08-24 15:48:26 -07005986/**
5987 * Ensure that separate calls to sign the same data are generating the same key.
5988 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5989 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5990 * tests.
5991 */
5992TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5993 KeyEvent event = getTestKeyEvent();
5994 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5995
5996 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5997 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5998 ASSERT_EQ(hmac1, hmac2);
5999}
6000
6001/**
6002 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6003 */
6004TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6005 KeyEvent event = getTestKeyEvent();
6006 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6007 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6008
6009 verifiedEvent.deviceId += 1;
6010 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6011
6012 verifiedEvent.source += 1;
6013 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6014
6015 verifiedEvent.eventTimeNanos += 1;
6016 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6017
6018 verifiedEvent.displayId += 1;
6019 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6020
6021 verifiedEvent.action += 1;
6022 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6023
6024 verifiedEvent.downTimeNanos += 1;
6025 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6026
6027 verifiedEvent.flags += 1;
6028 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6029
6030 verifiedEvent.keyCode += 1;
6031 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6032
6033 verifiedEvent.scanCode += 1;
6034 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6035
6036 verifiedEvent.metaState += 1;
6037 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6038
6039 verifiedEvent.repeatCount += 1;
6040 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6041}
6042
Vishnu Nair958da932020-08-21 17:12:37 -07006043TEST_F(InputDispatcherTest, SetFocusedWindow) {
6044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6045 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006046 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006047 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006048 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006049 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6050
6051 // Top window is also focusable but is not granted focus.
6052 windowTop->setFocusable(true);
6053 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006054 mDispatcher->onWindowInfosChanged(
6055 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006056 setFocusedWindow(windowSecond);
6057
6058 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006060 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006061
6062 // Focused window should receive event.
6063 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6064 windowTop->assertNoEvents();
6065}
6066
6067TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6069 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006070 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006071 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6072
6073 window->setFocusable(true);
6074 // Release channel for window is no longer valid.
6075 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006076 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006077 setFocusedWindow(window);
6078
6079 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006080 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006081
6082 // window channel is invalid, so it should not receive any input event.
6083 window->assertNoEvents();
6084}
6085
6086TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6088 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006089 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006090 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006091 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6092
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006093 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006094 setFocusedWindow(window);
6095
6096 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006097 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006098
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006099 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006100 window->assertNoEvents();
6101}
6102
6103TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6105 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006106 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006107 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006108 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6110
6111 windowTop->setFocusable(true);
6112 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006113 mDispatcher->onWindowInfosChanged(
6114 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006115 setFocusedWindow(windowTop);
6116 windowTop->consumeFocusEvent(true);
6117
Chavi Weingarten847e8512023-03-29 00:26:09 +00006118 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006119 mDispatcher->onWindowInfosChanged(
6120 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006121 windowSecond->consumeFocusEvent(true);
6122 windowTop->consumeFocusEvent(false);
6123
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006125 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006126
6127 // Focused window should receive event.
6128 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6129}
6130
Chavi Weingarten847e8512023-03-29 00:26:09 +00006131TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006132 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6133 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006134 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006135 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006136 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006137 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6138
6139 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006140 windowSecond->setFocusable(false);
6141 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged(
6143 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006144 setFocusedWindow(windowTop);
6145 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006146
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006148 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006149
6150 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006151 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006152 windowSecond->assertNoEvents();
6153}
6154
6155TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6157 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006158 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006159 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006160 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6161 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6163
6164 window->setFocusable(true);
6165 previousFocusedWindow->setFocusable(true);
6166 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006167 mDispatcher->onWindowInfosChanged(
6168 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006169 setFocusedWindow(previousFocusedWindow);
6170 previousFocusedWindow->consumeFocusEvent(true);
6171
6172 // Requesting focus on invisible window takes focus from currently focused window.
6173 setFocusedWindow(window);
6174 previousFocusedWindow->consumeFocusEvent(false);
6175
6176 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006178 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6179 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006180
6181 // Window does not get focus event or key down.
6182 window->assertNoEvents();
6183
6184 // Window becomes visible.
6185 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006186 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006187
6188 // Window receives focus event.
6189 window->consumeFocusEvent(true);
6190 // Focused window receives key down.
6191 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6192}
6193
Vishnu Nair599f1412021-06-21 10:39:58 -07006194TEST_F(InputDispatcherTest, DisplayRemoved) {
6195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6196 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006197 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006198 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6199
6200 // window is granted focus.
6201 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006202 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006203 setFocusedWindow(window);
6204 window->consumeFocusEvent(true);
6205
6206 // When a display is removed window loses focus.
6207 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6208 window->consumeFocusEvent(false);
6209}
6210
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006211/**
6212 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6213 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6214 * of the 'slipperyEnterWindow'.
6215 *
6216 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6217 * a way so that the touched location is no longer covered by the top window.
6218 *
6219 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6220 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6221 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6222 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6223 * with ACTION_DOWN).
6224 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6225 * window moved itself away from the touched location and had Flag::SLIPPERY.
6226 *
6227 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6228 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6229 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6230 *
6231 * In this test, we ensure that the event received by the bottom window has
6232 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6233 */
6234TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006235 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006236 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006237
6238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6239 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6240
6241 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006242 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006243 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006244 // Make sure this one overlaps the bottom window
6245 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6246 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6247 // one. Windows with the same owner are not considered to be occluding each other.
6248 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6249
6250 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006251 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006252 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6253
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006254 mDispatcher->onWindowInfosChanged(
6255 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006256
6257 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006258 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6259 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6260 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006261 slipperyExitWindow->consumeMotionDown();
6262 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006263 mDispatcher->onWindowInfosChanged(
6264 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006265
Prabir Pradhan678438e2023-04-13 19:32:51 +00006266 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6267 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6268 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006269
6270 slipperyExitWindow->consumeMotionCancel();
6271
6272 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6273 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6274}
6275
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006276/**
6277 * Two windows, one on the left and another on the right. The left window is slippery. The right
6278 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6279 * touch moves from the left window into the right window, the gesture should continue to go to the
6280 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6281 * reproduces a crash.
6282 */
6283TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6285
6286 sp<FakeWindowHandle> leftSlipperyWindow =
6287 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6288 leftSlipperyWindow->setSlippery(true);
6289 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6290
6291 sp<FakeWindowHandle> rightDropTouchesWindow =
6292 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6293 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6294 rightDropTouchesWindow->setDropInput(true);
6295
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006296 mDispatcher->onWindowInfosChanged(
6297 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006298
6299 // Start touch in the left window
6300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6301 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6302 .build());
6303 leftSlipperyWindow->consumeMotionDown();
6304
6305 // And move it into the right window
6306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6307 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6308 .build());
6309
6310 // Since the right window isn't eligible to receive input, touch does not slip.
6311 // The left window continues to receive the gesture.
6312 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6313 rightDropTouchesWindow->assertNoEvents();
6314}
6315
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006316/**
6317 * A single window is on screen first. Touch is injected into that window. Next, a second window
6318 * appears. Since the first window is slippery, touch will move from the first window to the second.
6319 */
6320TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6322 sp<FakeWindowHandle> originalWindow =
6323 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6324 originalWindow->setFrame(Rect(0, 0, 200, 200));
6325 originalWindow->setSlippery(true);
6326
6327 sp<FakeWindowHandle> appearingWindow =
6328 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6329 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6330
6331 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6332
6333 // Touch down on the original window
6334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6335 injectMotionEvent(*mDispatcher,
6336 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6337 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6338 .build()));
6339 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6340
6341 // Now, a new window appears. This could be, for example, a notification shade that appears
6342 // after user starts to drag down on the launcher window.
6343 mDispatcher->onWindowInfosChanged(
6344 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6346 injectMotionEvent(*mDispatcher,
6347 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6348 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6349 .build()));
6350 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6351 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6353 injectMotionEvent(*mDispatcher,
6354 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6355 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6356 .build()));
6357 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6358
6359 originalWindow->assertNoEvents();
6360 appearingWindow->assertNoEvents();
6361}
6362
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006363TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006364 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6366
6367 sp<FakeWindowHandle> leftWindow =
6368 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6369 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006370 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006371
6372 sp<FakeWindowHandle> rightSpy =
6373 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6374 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006375 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006376 rightSpy->setSpy(true);
6377 rightSpy->setTrustedOverlay(true);
6378
6379 sp<FakeWindowHandle> rightWindow =
6380 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6381 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006382 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006383
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006384 mDispatcher->onWindowInfosChanged(
6385 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006386
6387 // Touch in the left window
6388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6389 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6390 .build());
6391 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6392 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006393 ASSERT_NO_FATAL_FAILURE(
6394 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006395
6396 // Touch another finger over the right windows
6397 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6398 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6399 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6400 .build());
6401 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6402 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6403 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6404 mDispatcher->waitForIdle();
6405 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006406 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6407 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006408
6409 // Release finger over left window. The UP actions are not treated as device interaction.
6410 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6411 // is part of the UP action, we do not treat this as device interaction.
6412 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6413 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6414 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6415 .build());
6416 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6417 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6418 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6419 mDispatcher->waitForIdle();
6420 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6421
6422 // Move remaining finger
6423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6424 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6425 .build());
6426 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6427 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6428 mDispatcher->waitForIdle();
6429 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006430 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006431
6432 // Release all fingers
6433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6434 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6435 .build());
6436 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6437 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6438 mDispatcher->waitForIdle();
6439 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6440}
6441
6442TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6444
6445 sp<FakeWindowHandle> window =
6446 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6447 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006448 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006449
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006450 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006451 setFocusedWindow(window);
6452 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6453
6454 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6455 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6456 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006457 ASSERT_NO_FATAL_FAILURE(
6458 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006459
6460 // The UP actions are not treated as device interaction.
6461 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6462 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6463 mDispatcher->waitForIdle();
6464 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6465}
6466
Garfield Tan1c7bc862020-01-28 13:24:04 -08006467class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6468protected:
6469 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6470 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6471
Chris Yea209fde2020-07-22 13:54:51 -07006472 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006473 sp<FakeWindowHandle> mWindow;
6474
6475 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006476 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006477 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006478 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006479 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006480 ASSERT_EQ(OK, mDispatcher->start());
6481
6482 setUpWindow();
6483 }
6484
6485 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006486 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006487 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006488
Vishnu Nair47074b82020-08-14 11:54:47 -07006489 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006490 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006491 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006492 mWindow->consumeFocusEvent(true);
6493 }
6494
Chris Ye2ad95392020-09-01 13:44:44 -07006495 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006496 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006497 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006498 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006499 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006500
6501 // Window should receive key down event.
6502 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6503 }
6504
6505 void expectKeyRepeatOnce(int32_t repeatCount) {
6506 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006507 mWindow->consumeKeyEvent(
6508 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006509 }
6510
Chris Ye2ad95392020-09-01 13:44:44 -07006511 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006512 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006513 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006514 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006515 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006516
6517 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006518 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006519 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006520 }
6521};
6522
6523TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006524 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006525 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6526 expectKeyRepeatOnce(repeatCount);
6527 }
6528}
6529
6530TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006531 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006532 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6533 expectKeyRepeatOnce(repeatCount);
6534 }
Harry Cutts33476232023-01-30 19:57:29 +00006535 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006536 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006537 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6538 expectKeyRepeatOnce(repeatCount);
6539 }
6540}
6541
6542TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006543 sendAndConsumeKeyDown(/*deviceId=*/1);
6544 expectKeyRepeatOnce(/*repeatCount=*/1);
6545 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006546 mWindow->assertNoEvents();
6547}
6548
6549TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006550 sendAndConsumeKeyDown(/*deviceId=*/1);
6551 expectKeyRepeatOnce(/*repeatCount=*/1);
6552 sendAndConsumeKeyDown(/*deviceId=*/2);
6553 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006554 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006555 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006556 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006557 expectKeyRepeatOnce(/*repeatCount=*/2);
6558 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006559 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006560 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006561 mWindow->assertNoEvents();
6562}
6563
6564TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006565 sendAndConsumeKeyDown(/*deviceId=*/1);
6566 expectKeyRepeatOnce(/*repeatCount=*/1);
6567 sendAndConsumeKeyDown(/*deviceId=*/2);
6568 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006569 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006570 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006571 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006572 mWindow->assertNoEvents();
6573}
6574
liushenxiang42232912021-05-21 20:24:09 +08006575TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6576 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006577 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006578 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006579 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6580 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6581 mWindow->assertNoEvents();
6582}
6583
Garfield Tan1c7bc862020-01-28 13:24:04 -08006584TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006585 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006586 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006587 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006588 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006589 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6590 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6591 IdGenerator::getSource(repeatEvent->getId()));
6592 }
6593}
6594
6595TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006596 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006597 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006598
6599 std::unordered_set<int32_t> idSet;
6600 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006601 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006602 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6603 int32_t id = repeatEvent->getId();
6604 EXPECT_EQ(idSet.end(), idSet.find(id));
6605 idSet.insert(id);
6606 }
6607}
6608
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006609/* Test InputDispatcher for MultiDisplay */
6610class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6611public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006612 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006613 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006614
Chris Yea209fde2020-07-22 13:54:51 -07006615 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006616 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006617 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006618
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006619 // Set focus window for primary display, but focused display would be second one.
6620 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006621 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006622 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6623
Vishnu Nair958da932020-08-21 17:12:37 -07006624 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006625 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006626
Chris Yea209fde2020-07-22 13:54:51 -07006627 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006628 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006629 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006630 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006631 // Set focus display to second one.
6632 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6633 // Set focus window for second display.
6634 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006635 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006636 mDispatcher->onWindowInfosChanged(
6637 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006638 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006639 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006640 }
6641
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006642 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006643 InputDispatcherTest::TearDown();
6644
Chris Yea209fde2020-07-22 13:54:51 -07006645 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006646 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006647 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006648 windowInSecondary.clear();
6649 }
6650
6651protected:
Chris Yea209fde2020-07-22 13:54:51 -07006652 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006653 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006654 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006655 sp<FakeWindowHandle> windowInSecondary;
6656};
6657
6658TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6659 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006661 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006663 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006664 windowInSecondary->assertNoEvents();
6665
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006666 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006668 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006670 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006671 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006672}
6673
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006674TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006675 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006677 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006678 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006679 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006680 windowInSecondary->assertNoEvents();
6681
6682 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006684 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006685 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006686 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006687
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006688 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006689 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006690
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006691 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006692 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006693 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006694
6695 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006696 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006697 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006698 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006699 windowInSecondary->assertNoEvents();
6700}
6701
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006702// Test per-display input monitors for motion event.
6703TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006704 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006705 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006706 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006707 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006708
6709 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006713 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006714 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006715 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006716 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006717
6718 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006722 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006723 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006724 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006725 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006726
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006727 // Lift up the touch from the second display
6728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006729 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6731 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6732 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6733
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006734 // Test inject a non-pointer motion event.
6735 // If specific a display, it will dispatch to the focused window of particular display,
6736 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006738 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006740 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006741 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006742 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006743 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006744}
6745
6746// Test per-display input monitors for key event.
6747TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006748 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006749 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006750 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006751 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006752 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006753
6754 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006757 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006758 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006759 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006760 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006761}
6762
Vishnu Nair958da932020-08-21 17:12:37 -07006763TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6764 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006765 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006766 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006767 mDispatcher->onWindowInfosChanged(
6768 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6769 *windowInSecondary->getInfo()},
6770 {},
6771 0,
6772 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006773 setFocusedWindow(secondWindowInPrimary);
6774 windowInPrimary->consumeFocusEvent(false);
6775 secondWindowInPrimary->consumeFocusEvent(true);
6776
6777 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6779 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006780 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006781 windowInPrimary->assertNoEvents();
6782 windowInSecondary->assertNoEvents();
6783 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6784}
6785
Arthur Hungdfd528e2021-12-08 13:23:04 +00006786TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6787 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006788 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006789 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006790 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006791
6792 // Test touch down on primary display.
6793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006794 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6796 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6797 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6798
6799 // Test touch down on second display.
6800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6803 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6804 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6805
6806 // Trigger cancel touch.
6807 mDispatcher->cancelCurrentTouch();
6808 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6809 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6810 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6811 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6812
6813 // Test inject a move motion event, no window/monitor should receive the event.
6814 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006815 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006816 ADISPLAY_ID_DEFAULT, {110, 200}))
6817 << "Inject motion event should return InputEventInjectionResult::FAILED";
6818 windowInPrimary->assertNoEvents();
6819 monitorInPrimary.assertNoEvents();
6820
6821 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006822 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006823 SECOND_DISPLAY_ID, {110, 200}))
6824 << "Inject motion event should return InputEventInjectionResult::FAILED";
6825 windowInSecondary->assertNoEvents();
6826 monitorInSecondary.assertNoEvents();
6827}
6828
Jackal Guof9696682018-10-05 12:23:23 +08006829class InputFilterTest : public InputDispatcherTest {
6830protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006831 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6832 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006833 NotifyMotionArgs motionArgs;
6834
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006835 motionArgs =
6836 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006837 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006838 motionArgs =
6839 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006840 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006841 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006842 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006843 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006844 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006845 } else {
6846 mFakePolicy->assertFilterInputEventWasNotCalled();
6847 }
6848 }
6849
6850 void testNotifyKey(bool expectToBeFiltered) {
6851 NotifyKeyArgs keyArgs;
6852
6853 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006854 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006855 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006856 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006857 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006858
6859 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006860 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006861 } else {
6862 mFakePolicy->assertFilterInputEventWasNotCalled();
6863 }
6864 }
6865};
6866
6867// Test InputFilter for MotionEvent
6868TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6869 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006870 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6871 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006872
6873 // Enable InputFilter
6874 mDispatcher->setInputFilterEnabled(true);
6875 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006876 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6877 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006878
6879 // Disable InputFilter
6880 mDispatcher->setInputFilterEnabled(false);
6881 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006882 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6883 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006884}
6885
6886// Test InputFilter for KeyEvent
6887TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6888 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006889 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006890
6891 // Enable InputFilter
6892 mDispatcher->setInputFilterEnabled(true);
6893 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006894 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006895
6896 // Disable InputFilter
6897 mDispatcher->setInputFilterEnabled(false);
6898 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006899 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006900}
6901
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006902// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6903// logical display coordinate space.
6904TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6905 ui::Transform firstDisplayTransform;
6906 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6907 ui::Transform secondDisplayTransform;
6908 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6909
6910 std::vector<gui::DisplayInfo> displayInfos(2);
6911 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6912 displayInfos[0].transform = firstDisplayTransform;
6913 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6914 displayInfos[1].transform = secondDisplayTransform;
6915
Patrick Williamsd828f302023-04-28 17:52:08 -05006916 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006917
6918 // Enable InputFilter
6919 mDispatcher->setInputFilterEnabled(true);
6920
6921 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006922 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6923 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006924}
6925
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006926class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6927protected:
6928 virtual void SetUp() override {
6929 InputDispatcherTest::SetUp();
6930
6931 /**
6932 * We don't need to enable input filter to test the injected event policy, but we enabled it
6933 * here to make the tests more realistic, since this policy only matters when inputfilter is
6934 * on.
6935 */
6936 mDispatcher->setInputFilterEnabled(true);
6937
6938 std::shared_ptr<InputApplicationHandle> application =
6939 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006940 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6941 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006942
6943 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6944 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006945 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006946 setFocusedWindow(mWindow);
6947 mWindow->consumeFocusEvent(true);
6948 }
6949
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006950 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6951 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006952 KeyEvent event;
6953
6954 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6955 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6956 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006957 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006958 const int32_t additionalPolicyFlags =
6959 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006961 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006962 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006963 policyFlags | additionalPolicyFlags));
6964
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006965 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006966 }
6967
6968 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6969 int32_t flags) {
6970 MotionEvent event;
6971 PointerProperties pointerProperties[1];
6972 PointerCoords pointerCoords[1];
6973 pointerProperties[0].clear();
6974 pointerProperties[0].id = 0;
6975 pointerCoords[0].clear();
6976 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6977 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6978
6979 ui::Transform identityTransform;
6980 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6981 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6982 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6983 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6984 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006985 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006986 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006987 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006988
6989 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006991 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006992 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006993 policyFlags | additionalPolicyFlags));
6994
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006995 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006996 }
6997
6998private:
6999 sp<FakeWindowHandle> mWindow;
7000};
7001
7002TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007003 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7004 // filter. Without it, the event will no different from a regularly injected event, and the
7005 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007006 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7007 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007008}
7009
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007010TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007011 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007012 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007013 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7014}
7015
7016TEST_F(InputFilterInjectionPolicyTest,
7017 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7018 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007019 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007020 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007021}
7022
7023TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007024 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7025 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007026}
7027
chaviwfd6d3512019-03-25 13:23:49 -07007028class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007029 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007030 InputDispatcherTest::SetUp();
7031
Chris Yea209fde2020-07-22 13:54:51 -07007032 std::shared_ptr<FakeApplicationHandle> application =
7033 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007034 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007035 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007036 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007037
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007038 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007039 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007040 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007041
7042 // Set focused application.
7043 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007044 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007045
7046 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007047 mDispatcher->onWindowInfosChanged(
7048 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007049 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007050 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007051 }
7052
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007053 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007054 InputDispatcherTest::TearDown();
7055
7056 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007057 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007058 }
7059
7060protected:
7061 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007062 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007063 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007064};
7065
7066// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7067// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7068// the onPointerDownOutsideFocus callback.
7069TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007071 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007072 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007074 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007075
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007076 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007077 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7078}
7079
7080// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7081// DOWN on the window that doesn't have focus. Ensure no window received the
7082// onPointerDownOutsideFocus callback.
7083TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007085 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7086 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007088 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007089
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007090 ASSERT_TRUE(mDispatcher->waitForIdle());
7091 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007092}
7093
7094// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7095// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7096TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007098 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007099 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007100 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007101
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007102 ASSERT_TRUE(mDispatcher->waitForIdle());
7103 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007104}
7105
7106// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7107// DOWN on the window that already has focus. Ensure no window received the
7108// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007109TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007111 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007112 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007113 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007114 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007115
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007116 ASSERT_TRUE(mDispatcher->waitForIdle());
7117 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007118}
7119
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007120// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7121// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7122TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7123 const MotionEvent event =
7124 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7125 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007126 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007127 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7128 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7131 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7132
7133 ASSERT_TRUE(mDispatcher->waitForIdle());
7134 mFakePolicy->assertOnPointerDownWasNotCalled();
7135 // Ensure that the unfocused window did not receive any FOCUS events.
7136 mUnfocusedWindow->assertNoEvents();
7137}
7138
chaviwaf87b3e2019-10-01 16:59:28 -07007139// These tests ensures we can send touch events to a single client when there are multiple input
7140// windows that point to the same client token.
7141class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7142 virtual void SetUp() override {
7143 InputDispatcherTest::SetUp();
7144
Chris Yea209fde2020-07-22 13:54:51 -07007145 std::shared_ptr<FakeApplicationHandle> application =
7146 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007147 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7148 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007149 mWindow1->setFrame(Rect(0, 0, 100, 100));
7150
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007151 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7152 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007153 mWindow2->setFrame(Rect(100, 100, 200, 200));
7154
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007155 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007156 }
7157
7158protected:
7159 sp<FakeWindowHandle> mWindow1;
7160 sp<FakeWindowHandle> mWindow2;
7161
7162 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007163 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007164 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7165 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007166 }
7167
7168 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7169 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007170 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007171 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007172
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007173 ASSERT_NE(nullptr, motionEvent)
7174 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007175
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007176 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007177 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007178
7179 for (size_t i = 0; i < points.size(); i++) {
7180 float expectedX = points[i].x;
7181 float expectedY = points[i].y;
7182
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007183 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007184 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007185 << ", got " << motionEvent->getX(i);
7186 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007187 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007188 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007189 }
7190 }
chaviw9eaa22c2020-07-01 16:21:27 -07007191
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007192 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007193 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007194 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7195 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007196
7197 // Always consume from window1 since it's the window that has the InputReceiver
7198 consumeMotionEvent(mWindow1, action, expectedPoints);
7199 }
chaviwaf87b3e2019-10-01 16:59:28 -07007200};
7201
7202TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7203 // Touch Window 1
7204 PointF touchedPoint = {10, 10};
7205 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007206 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007207
7208 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007209 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007210
7211 // Touch Window 2
7212 touchedPoint = {150, 150};
7213 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007214 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007215}
7216
chaviw9eaa22c2020-07-01 16:21:27 -07007217TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7218 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007219 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007220 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007221
7222 // Touch Window 1
7223 PointF touchedPoint = {10, 10};
7224 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007225 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007226 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007227 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007228
7229 // Touch Window 2
7230 touchedPoint = {150, 150};
7231 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007232 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7233 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007234
chaviw9eaa22c2020-07-01 16:21:27 -07007235 // Update the transform so rotation is set
7236 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007237 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007238 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7239 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007240}
7241
chaviw9eaa22c2020-07-01 16:21:27 -07007242TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007243 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007244 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007245
7246 // Touch Window 1
7247 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7248 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007249 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007250
7251 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007252 touchedPoints.push_back(PointF{150, 150});
7253 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007254 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007255
chaviw9eaa22c2020-07-01 16:21:27 -07007256 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007257 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007258 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007259
chaviw9eaa22c2020-07-01 16:21:27 -07007260 // Update the transform so rotation is set for Window 2
7261 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007262 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007263 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007264 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007265}
7266
chaviw9eaa22c2020-07-01 16:21:27 -07007267TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007268 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007269 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007270
7271 // Touch Window 1
7272 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7273 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007274 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007275
7276 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007277 touchedPoints.push_back(PointF{150, 150});
7278 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007279
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007280 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007281
7282 // Move both windows
7283 touchedPoints = {{20, 20}, {175, 175}};
7284 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7285 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7286
chaviw9eaa22c2020-07-01 16:21:27 -07007287 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007288
chaviw9eaa22c2020-07-01 16:21:27 -07007289 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007290 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007291 expectedPoints.pop_back();
7292
7293 // Touch Window 2
7294 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007295 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007296 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007297 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007298
7299 // Move both windows
7300 touchedPoints = {{20, 20}, {175, 175}};
7301 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7302 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7303
7304 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007305}
7306
7307TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7308 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007309 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007310
7311 // Touch Window 1
7312 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7313 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007314 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007315
7316 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007317 touchedPoints.push_back(PointF{150, 150});
7318 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007319
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007320 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007321
7322 // Move both windows
7323 touchedPoints = {{20, 20}, {175, 175}};
7324 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7325 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7326
chaviw9eaa22c2020-07-01 16:21:27 -07007327 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007328}
7329
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007330/**
7331 * When one of the windows is slippery, the touch should not slip into the other window with the
7332 * same input channel.
7333 */
7334TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7335 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007336 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007337
7338 // Touch down in window 1
7339 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7340 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7341 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7342
7343 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7344 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7345 // getting generated.
7346 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7347 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7348
7349 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7350}
7351
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007352/**
7353 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7354 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7355 * that the pointer is hovering over may have a different transform.
7356 */
7357TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007358 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007359
7360 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007361 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7362 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7363 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007364 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7365 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007366 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007367 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7368 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7369 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007370 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7371 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7372 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7373}
7374
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007375class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7376 virtual void SetUp() override {
7377 InputDispatcherTest::SetUp();
7378
Chris Yea209fde2020-07-22 13:54:51 -07007379 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007380 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007381 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7382 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007383 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007384 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007385 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007386
7387 // Set focused application.
7388 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7389
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007390 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007391 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007392 mWindow->consumeFocusEvent(true);
7393 }
7394
7395 virtual void TearDown() override {
7396 InputDispatcherTest::TearDown();
7397 mWindow.clear();
7398 }
7399
7400protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007401 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007402 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007403 sp<FakeWindowHandle> mWindow;
7404 static constexpr PointF WINDOW_LOCATION = {20, 20};
7405
7406 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007408 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007409 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007411 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007412 WINDOW_LOCATION));
7413 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007414
7415 sp<FakeWindowHandle> addSpyWindow() {
7416 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007417 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007418 spy->setTrustedOverlay(true);
7419 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007420 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007421 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007422 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007423 return spy;
7424 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007425};
7426
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007427// Send a tap and respond, which should not cause an ANR.
7428TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7429 tapOnWindow();
7430 mWindow->consumeMotionDown();
7431 mWindow->consumeMotionUp();
7432 ASSERT_TRUE(mDispatcher->waitForIdle());
7433 mFakePolicy->assertNotifyAnrWasNotCalled();
7434}
7435
7436// Send a regular key and respond, which should not cause an ANR.
7437TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007439 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7440 ASSERT_TRUE(mDispatcher->waitForIdle());
7441 mFakePolicy->assertNotifyAnrWasNotCalled();
7442}
7443
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007444TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7445 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007446 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007447 mWindow->consumeFocusEvent(false);
7448
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007449 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007450 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7451 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007452 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007454 // Key will not go to window because we have no focused window.
7455 // The 'no focused window' ANR timer should start instead.
7456
7457 // Now, the focused application goes away.
7458 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7459 // The key should get dropped and there should be no ANR.
7460
7461 ASSERT_TRUE(mDispatcher->waitForIdle());
7462 mFakePolicy->assertNotifyAnrWasNotCalled();
7463}
7464
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007465// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007466// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7467// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007468TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007470 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007471 WINDOW_LOCATION));
7472
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007473 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7474 ASSERT_TRUE(sequenceNum);
7475 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007476 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007477
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007478 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007479 mWindow->consumeMotionEvent(
7480 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007481 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007482 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007483}
7484
7485// Send a key to the app and have the app not respond right away.
7486TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7487 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007489 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7490 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007491 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007492 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007493 ASSERT_TRUE(mDispatcher->waitForIdle());
7494}
7495
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007496// We have a focused application, but no focused window
7497TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007498 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007499 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007500 mWindow->consumeFocusEvent(false);
7501
7502 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007504 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007505 WINDOW_LOCATION));
7506 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7507 mDispatcher->waitForIdle();
7508 mFakePolicy->assertNotifyAnrWasNotCalled();
7509
7510 // Once a focused event arrives, we get an ANR for this application
7511 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7512 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007513 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007514 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007515 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007516 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007517 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007518 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007519 ASSERT_TRUE(mDispatcher->waitForIdle());
7520}
7521
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007522/**
7523 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7524 * there will not be an ANR.
7525 */
7526TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7527 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007528 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007529 mWindow->consumeFocusEvent(false);
7530
7531 KeyEvent event;
7532 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7533 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7534
7535 // Define a valid key down event that is stale (too old).
7536 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007537 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007538 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007539
7540 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7541
7542 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007543 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007544 InputEventInjectionSync::WAIT_FOR_RESULT,
7545 INJECT_EVENT_TIMEOUT, policyFlags);
7546 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7547 << "Injection should fail because the event is stale";
7548
7549 ASSERT_TRUE(mDispatcher->waitForIdle());
7550 mFakePolicy->assertNotifyAnrWasNotCalled();
7551 mWindow->assertNoEvents();
7552}
7553
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007554// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007555// Make sure that we don't notify policy twice about the same ANR.
7556TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007557 const std::chrono::duration appTimeout = 400ms;
7558 mApplication->setDispatchingTimeout(appTimeout);
7559 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7560
Vishnu Nair47074b82020-08-14 11:54:47 -07007561 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007562 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007563 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007564
7565 // Once a focused event arrives, we get an ANR for this application
7566 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7567 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007568 const std::chrono::duration eventInjectionTimeout = 100ms;
7569 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007570 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007571 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007572 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7573 /*allowKeyRepeat=*/false);
7574 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7575 << "result=" << ftl::enum_string(result);
7576 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7577 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7578 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7579 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007580
Vishnu Naire4df8752022-09-08 09:17:55 -07007581 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007582 // ANR should not be raised again. It is up to policy to do that if it desires.
7583 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007584
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007585 // If we now get a focused window, the ANR should stop, but the policy handles that via
7586 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007587 ASSERT_TRUE(mDispatcher->waitForIdle());
7588}
7589
7590// We have a focused application, but no focused window
7591TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007592 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007593 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007594 mWindow->consumeFocusEvent(false);
7595
7596 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007597 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007598
Vishnu Naire4df8752022-09-08 09:17:55 -07007599 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7600 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007601
7602 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007603 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007604 ASSERT_TRUE(mDispatcher->waitForIdle());
7605 mWindow->assertNoEvents();
7606}
7607
7608/**
7609 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7610 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7611 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7612 * the ANR mechanism should still work.
7613 *
7614 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7615 * DOWN event, while not responding on the second one.
7616 */
7617TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7618 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007619 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007620 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7621 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7622 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007623 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007624
7625 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007626 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007627 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7628 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7629 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007630 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007631
7632 // We have now sent down and up. Let's consume first event and then ANR on the second.
7633 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7634 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007635 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007636}
7637
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007638// A spy window can receive an ANR
7639TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7640 sp<FakeWindowHandle> spy = addSpyWindow();
7641
7642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007643 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007644 WINDOW_LOCATION));
7645 mWindow->consumeMotionDown();
7646
7647 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7648 ASSERT_TRUE(sequenceNum);
7649 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007650 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007651
7652 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007653 spy->consumeMotionEvent(
7654 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007655 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007656 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007657}
7658
7659// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007660// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007661TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7662 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007663
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007665 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007666 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007668
7669 // Stuck on the ACTION_UP
7670 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007671 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007672
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007673 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007674 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007675 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7676 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007677
7678 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7679 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007680 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007681 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007682 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007683}
7684
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007685// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007686// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007687TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7688 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007689
7690 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007691 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7692 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007693
7694 mWindow->consumeMotionDown();
7695 // Stuck on the ACTION_UP
7696 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007697 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007698
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007699 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007700 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007701 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7702 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007703
7704 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7705 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007706 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007707 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007708 spy->assertNoEvents();
7709}
7710
7711TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007712 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007713
Prabir Pradhanfb549072023-10-05 19:17:36 +00007714 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007715
7716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007718 WINDOW_LOCATION));
7719
7720 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7721 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7722 ASSERT_TRUE(consumeSeq);
7723
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007724 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7725 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007726
7727 monitor.finishEvent(*consumeSeq);
7728 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7729
7730 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007731 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007732}
7733
7734// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7735// process events, you don't get an anr. When the window later becomes unresponsive again, you
7736// get an ANR again.
7737// 1. tap -> block on ACTION_UP -> receive ANR
7738// 2. consume all pending events (= queue becomes healthy again)
7739// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7740TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7741 tapOnWindow();
7742
7743 mWindow->consumeMotionDown();
7744 // Block on ACTION_UP
7745 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007746 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007747 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7748 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007749 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007750 mWindow->assertNoEvents();
7751
7752 tapOnWindow();
7753 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007754 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007755 mWindow->consumeMotionUp();
7756
7757 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007758 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007759 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007760 mWindow->assertNoEvents();
7761}
7762
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007763// If a connection remains unresponsive for a while, make sure policy is only notified once about
7764// it.
7765TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007767 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007768 WINDOW_LOCATION));
7769
7770 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007771 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007772 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007773 // 'notifyConnectionUnresponsive' should only be called once per connection
7774 mFakePolicy->assertNotifyAnrWasNotCalled();
7775 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007776 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007777 mWindow->consumeMotionEvent(
7778 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007779 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007780 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007781 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007782 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007783}
7784
7785/**
7786 * 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 -07007787 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007788 *
7789 * Warning!!!
7790 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7791 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007792 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007793 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7794 *
7795 * If that value changes, this test should also change.
7796 */
7797TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7798 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007799 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007800
7801 tapOnWindow();
7802 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7803 ASSERT_TRUE(downSequenceNum);
7804 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7805 ASSERT_TRUE(upSequenceNum);
7806 // Don't finish the events yet, and send a key
7807 // Injection will "succeed" because we will eventually give up and send the key to the focused
7808 // window even if motions are still being processed. But because the injection timeout is short,
7809 // we will receive INJECTION_TIMED_OUT as the result.
7810
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007811 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007812 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7813 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007814 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007815 // Key will not be sent to the window, yet, because the window is still processing events
7816 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007817 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7818 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7819 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7820 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007821
7822 std::this_thread::sleep_for(500ms);
7823 // if we wait long enough though, dispatcher will give up, and still send the key
7824 // to the focused window, even though we have not yet finished the motion event
7825 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7826 mWindow->finishEvent(*downSequenceNum);
7827 mWindow->finishEvent(*upSequenceNum);
7828}
7829
7830/**
7831 * If a window is processing a motion event, and then a key event comes in, the key event should
7832 * not go to the focused window until the motion is processed.
7833 * If then a new motion comes in, then the pending key event should be going to the currently
7834 * focused window right away.
7835 */
7836TEST_F(InputDispatcherSingleWindowAnr,
7837 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7838 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007839 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007840
7841 tapOnWindow();
7842 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7843 ASSERT_TRUE(downSequenceNum);
7844 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7845 ASSERT_TRUE(upSequenceNum);
7846 // Don't finish the events yet, and send a key
7847 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007849 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7850 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007851 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007852 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7853 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7854 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7855 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007856
7857 // Now tap down again. It should cause the pending key to go to the focused window right away.
7858 tapOnWindow();
7859 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7860 // the other events yet. We can finish events in any order.
7861 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7862 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7863 mWindow->consumeMotionDown();
7864 mWindow->consumeMotionUp();
7865 mWindow->assertNoEvents();
7866}
7867
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007868/**
7869 * Send an event to the app and have the app not respond right away.
7870 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7871 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7872 * At some point, the window becomes responsive again.
7873 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7874 */
7875TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7877 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7878 .build());
7879
7880 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7881 ASSERT_TRUE(sequenceNum);
7882 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7883 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7884
7885 mWindow->finishEvent(*sequenceNum);
7886 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7887 ASSERT_TRUE(mDispatcher->waitForIdle());
7888 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7889
7890 // Now that the window is responsive, let's continue the gesture.
7891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7892 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7893 .build());
7894
7895 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7896 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7897 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7898 .build());
7899
7900 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7901 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7902 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7903 .build());
7904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7905 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7906 .build());
7907 // We already canceled this pointer, so the window shouldn't get any new events.
7908 mWindow->assertNoEvents();
7909
7910 // Start another one.
7911 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7912 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7913 .build());
7914 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7915}
7916
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007917class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7918 virtual void SetUp() override {
7919 InputDispatcherTest::SetUp();
7920
Chris Yea209fde2020-07-22 13:54:51 -07007921 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007922 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007923 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7924 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007925 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007926 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007927 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007928
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007929 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7930 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007931 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007932 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007933
7934 // Set focused application.
7935 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007936 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007937
7938 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007939 mDispatcher->onWindowInfosChanged(
7940 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007941 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942 mFocusedWindow->consumeFocusEvent(true);
7943 }
7944
7945 virtual void TearDown() override {
7946 InputDispatcherTest::TearDown();
7947
7948 mUnfocusedWindow.clear();
7949 mFocusedWindow.clear();
7950 }
7951
7952protected:
Chris Yea209fde2020-07-22 13:54:51 -07007953 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007954 sp<FakeWindowHandle> mUnfocusedWindow;
7955 sp<FakeWindowHandle> mFocusedWindow;
7956 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7957 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7958 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7959
7960 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7961
7962 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7963
7964private:
7965 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007967 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007968 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007970 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007971 location));
7972 }
7973};
7974
7975// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7976// should be ANR'd first.
7977TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07007979 injectMotionEvent(*mDispatcher,
7980 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7981 AINPUT_SOURCE_TOUCHSCREEN)
7982 .pointer(PointerBuilder(0, ToolType::FINGER)
7983 .x(FOCUSED_WINDOW_LOCATION.x)
7984 .y(FOCUSED_WINDOW_LOCATION.y))
7985 .build()));
7986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7987 injectMotionEvent(*mDispatcher,
7988 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
7989 AINPUT_SOURCE_TOUCHSCREEN)
7990 .pointer(PointerBuilder(0, ToolType::FINGER)
7991 .x(FOCUSED_WINDOW_LOCATION.x)
7992 .y(FOCUSED_WINDOW_LOCATION.y))
7993 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007994 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07007995 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007996 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007997 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007998 // We consumed all events, so no ANR
7999 ASSERT_TRUE(mDispatcher->waitForIdle());
8000 mFakePolicy->assertNotifyAnrWasNotCalled();
8001
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008003 injectMotionEvent(*mDispatcher,
8004 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8005 AINPUT_SOURCE_TOUCHSCREEN)
8006 .pointer(PointerBuilder(0, ToolType::FINGER)
8007 .x(FOCUSED_WINDOW_LOCATION.x)
8008 .y(FOCUSED_WINDOW_LOCATION.y))
8009 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008010 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8011 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008012
8013 const std::chrono::duration timeout =
8014 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008015 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008016
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008017 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008018 mFocusedWindow->consumeMotionDown();
8019 // This cancel is generated because the connection was unresponsive
8020 mFocusedWindow->consumeMotionCancel();
8021 mFocusedWindow->assertNoEvents();
8022 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008023 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008024 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8025 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008026 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008027}
8028
8029// If we have 2 windows with identical timeouts that are both unresponsive,
8030// it doesn't matter which order they should have ANR.
8031// But we should receive ANR for both.
8032TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8033 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008034 mUnfocusedWindow->setDispatchingTimeout(
8035 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008036 mDispatcher->onWindowInfosChanged(
8037 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008038
8039 tapOnFocusedWindow();
8040 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008041 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008042 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8043 mFocusedWindow->getDispatchingTimeout(
8044 DISPATCHING_TIMEOUT)),
8045 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8046
8047 ASSERT_THAT(anrConnectionTokens,
8048 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8049 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008050
8051 ASSERT_TRUE(mDispatcher->waitForIdle());
8052 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008053
8054 mFocusedWindow->consumeMotionDown();
8055 mFocusedWindow->consumeMotionUp();
8056 mUnfocusedWindow->consumeMotionOutside();
8057
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008058 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8059 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008060
8061 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008062 ASSERT_THAT(responsiveTokens,
8063 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8064 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008065 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008066}
8067
8068// If a window is already not responding, the second tap on the same window should be ignored.
8069// We should also log an error to account for the dropped event (not tested here).
8070// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8071TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8072 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008073 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008074 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008075 // Receive the events, but don't respond
8076 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8077 ASSERT_TRUE(downEventSequenceNum);
8078 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8079 ASSERT_TRUE(upEventSequenceNum);
8080 const std::chrono::duration timeout =
8081 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008082 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008083
8084 // Tap once again
8085 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008086 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008087 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008088 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008089 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008090 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008091 FOCUSED_WINDOW_LOCATION));
8092 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8093 // valid touch target
8094 mUnfocusedWindow->assertNoEvents();
8095
8096 // Consume the first tap
8097 mFocusedWindow->finishEvent(*downEventSequenceNum);
8098 mFocusedWindow->finishEvent(*upEventSequenceNum);
8099 ASSERT_TRUE(mDispatcher->waitForIdle());
8100 // The second tap did not go to the focused window
8101 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008102 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008103 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8104 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008105 mFakePolicy->assertNotifyAnrWasNotCalled();
8106}
8107
8108// If you tap outside of all windows, there will not be ANR
8109TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008110 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008111 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008112 LOCATION_OUTSIDE_ALL_WINDOWS));
8113 ASSERT_TRUE(mDispatcher->waitForIdle());
8114 mFakePolicy->assertNotifyAnrWasNotCalled();
8115}
8116
8117// Since the focused window is paused, tapping on it should not produce any events
8118TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8119 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008120 mDispatcher->onWindowInfosChanged(
8121 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008122
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008123 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008124 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008125 FOCUSED_WINDOW_LOCATION));
8126
8127 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8128 ASSERT_TRUE(mDispatcher->waitForIdle());
8129 // Should not ANR because the window is paused, and touches shouldn't go to it
8130 mFakePolicy->assertNotifyAnrWasNotCalled();
8131
8132 mFocusedWindow->assertNoEvents();
8133 mUnfocusedWindow->assertNoEvents();
8134}
8135
8136/**
8137 * 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 -07008138 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008139 * If a different window becomes focused at this time, the key should go to that window instead.
8140 *
8141 * Warning!!!
8142 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8143 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008144 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008145 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8146 *
8147 * If that value changes, this test should also change.
8148 */
8149TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8150 // Set a long ANR timeout to prevent it from triggering
8151 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008152 mDispatcher->onWindowInfosChanged(
8153 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008154
8155 tapOnUnfocusedWindow();
8156 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8157 ASSERT_TRUE(downSequenceNum);
8158 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8159 ASSERT_TRUE(upSequenceNum);
8160 // Don't finish the events yet, and send a key
8161 // Injection will succeed because we will eventually give up and send the key to the focused
8162 // window even if motions are still being processed.
8163
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008164 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008165 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8166 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008168 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008169 // and the key remains pending, waiting for the touch events to be processed.
8170 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8171 // under the hood.
8172 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8173 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008174
8175 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008176 mFocusedWindow->setFocusable(false);
8177 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008178 mDispatcher->onWindowInfosChanged(
8179 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008180 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008181
8182 // Focus events should precede the key events
8183 mUnfocusedWindow->consumeFocusEvent(true);
8184 mFocusedWindow->consumeFocusEvent(false);
8185
8186 // Finish the tap events, which should unblock dispatcher
8187 mUnfocusedWindow->finishEvent(*downSequenceNum);
8188 mUnfocusedWindow->finishEvent(*upSequenceNum);
8189
8190 // Now that all queues are cleared and no backlog in the connections, the key event
8191 // can finally go to the newly focused "mUnfocusedWindow".
8192 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8193 mFocusedWindow->assertNoEvents();
8194 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008195 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008196}
8197
8198// When the touch stream is split across 2 windows, and one of them does not respond,
8199// then ANR should be raised and the touch should be canceled for the unresponsive window.
8200// The other window should not be affected by that.
8201TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8202 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008203 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8204 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8205 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008206 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008207 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008208
8209 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008210 mDispatcher->notifyMotion(
8211 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8212 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008213
8214 const std::chrono::duration timeout =
8215 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008216 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008217
8218 mUnfocusedWindow->consumeMotionDown();
8219 mFocusedWindow->consumeMotionDown();
8220 // Focused window may or may not receive ACTION_MOVE
8221 // But it should definitely receive ACTION_CANCEL due to the ANR
8222 InputEvent* event;
8223 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8224 ASSERT_TRUE(moveOrCancelSequenceNum);
8225 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8226 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008227 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008228 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8229 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8230 mFocusedWindow->consumeMotionCancel();
8231 } else {
8232 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8233 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008234 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008235 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8236 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008237
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008238 mUnfocusedWindow->assertNoEvents();
8239 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008240 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008241}
8242
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008243/**
8244 * If we have no focused window, and a key comes in, we start the ANR timer.
8245 * The focused application should add a focused window before the timer runs out to prevent ANR.
8246 *
8247 * If the user touches another application during this time, the key should be dropped.
8248 * Next, if a new focused window comes in, without toggling the focused application,
8249 * then no ANR should occur.
8250 *
8251 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8252 * but in some cases the policy may not update the focused application.
8253 */
8254TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8255 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8256 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008257 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008258 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8259 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8260 mFocusedWindow->setFocusable(false);
8261
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008262 mDispatcher->onWindowInfosChanged(
8263 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008264 mFocusedWindow->consumeFocusEvent(false);
8265
8266 // Send a key. The ANR timer should start because there is no focused window.
8267 // 'focusedApplication' will get blamed if this timer completes.
8268 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008269 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008270 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8271 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008272 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008274
8275 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8276 // then the injected touches won't cause the focused event to get dropped.
8277 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8278 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8279 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8280 // For this test, it means that the key would get delivered to the window once it becomes
8281 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008282 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008283
8284 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008285 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8286 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8287 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008288
8289 // We do not consume the motion right away, because that would require dispatcher to first
8290 // process (== drop) the key event, and by that time, ANR will be raised.
8291 // Set the focused window first.
8292 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008293 mDispatcher->onWindowInfosChanged(
8294 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008295 setFocusedWindow(mFocusedWindow);
8296 mFocusedWindow->consumeFocusEvent(true);
8297 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8298 // to another application. This could be a bug / behaviour in the policy.
8299
8300 mUnfocusedWindow->consumeMotionDown();
8301
8302 ASSERT_TRUE(mDispatcher->waitForIdle());
8303 // Should not ANR because we actually have a focused window. It was just added too slowly.
8304 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8305}
8306
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008307// These tests ensure we cannot send touch events to a window that's positioned behind a window
8308// that has feature NO_INPUT_CHANNEL.
8309// Layout:
8310// Top (closest to user)
8311// mNoInputWindow (above all windows)
8312// mBottomWindow
8313// Bottom (furthest from user)
8314class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8315 virtual void SetUp() override {
8316 InputDispatcherTest::SetUp();
8317
8318 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008319 mNoInputWindow =
8320 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8321 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008322 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008323 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008324 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8325 // It's perfectly valid for this window to not have an associated input channel
8326
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008327 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8328 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008329 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8330
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008331 mDispatcher->onWindowInfosChanged(
8332 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008333 }
8334
8335protected:
8336 std::shared_ptr<FakeApplicationHandle> mApplication;
8337 sp<FakeWindowHandle> mNoInputWindow;
8338 sp<FakeWindowHandle> mBottomWindow;
8339};
8340
8341TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8342 PointF touchedPoint = {10, 10};
8343
Prabir Pradhan678438e2023-04-13 19:32:51 +00008344 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8345 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8346 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008347
8348 mNoInputWindow->assertNoEvents();
8349 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8350 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8351 // and therefore should prevent mBottomWindow from receiving touches
8352 mBottomWindow->assertNoEvents();
8353}
8354
8355/**
8356 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8357 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8358 */
8359TEST_F(InputDispatcherMultiWindowOcclusionTests,
8360 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008361 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8362 "Window with input channel and NO_INPUT_CHANNEL",
8363 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008364
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008365 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008366 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008367 mDispatcher->onWindowInfosChanged(
8368 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008369
8370 PointF touchedPoint = {10, 10};
8371
Prabir Pradhan678438e2023-04-13 19:32:51 +00008372 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8373 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8374 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008375
8376 mNoInputWindow->assertNoEvents();
8377 mBottomWindow->assertNoEvents();
8378}
8379
Vishnu Nair958da932020-08-21 17:12:37 -07008380class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8381protected:
8382 std::shared_ptr<FakeApplicationHandle> mApp;
8383 sp<FakeWindowHandle> mWindow;
8384 sp<FakeWindowHandle> mMirror;
8385
8386 virtual void SetUp() override {
8387 InputDispatcherTest::SetUp();
8388 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008389 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8390 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8391 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008392 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8393 mWindow->setFocusable(true);
8394 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008395 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008396 }
8397};
8398
8399TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8400 // Request focus on a mirrored window
8401 setFocusedWindow(mMirror);
8402
8403 // window gets focused
8404 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008406 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008407 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8408}
8409
8410// A focused & mirrored window remains focused only if the window and its mirror are both
8411// focusable.
8412TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8413 setFocusedWindow(mMirror);
8414
8415 // window gets focused
8416 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008418 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008419 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008421 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008422 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8423
8424 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008425 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008426
8427 // window loses focus since one of the windows associated with the token in not focusable
8428 mWindow->consumeFocusEvent(false);
8429
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008430 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008431 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008432 mWindow->assertNoEvents();
8433}
8434
8435// A focused & mirrored window remains focused until the window and its mirror both become
8436// invisible.
8437TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8438 setFocusedWindow(mMirror);
8439
8440 // window gets focused
8441 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008443 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008444 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008446 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008447 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8448
8449 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008450 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008451
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008453 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008454 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008456 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008457 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8458
8459 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008460 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008461
8462 // window loses focus only after all windows associated with the token become invisible.
8463 mWindow->consumeFocusEvent(false);
8464
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008465 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008466 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008467 mWindow->assertNoEvents();
8468}
8469
8470// A focused & mirrored window remains focused until both windows are removed.
8471TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8472 setFocusedWindow(mMirror);
8473
8474 // window gets focused
8475 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008477 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008478 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008480 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008481 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8482
8483 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008484 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008485
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008487 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008488 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008490 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008491 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8492
8493 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008494 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008495 mWindow->consumeFocusEvent(false);
8496
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008497 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008498 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008499 mWindow->assertNoEvents();
8500}
8501
8502// Focus request can be pending until one window becomes visible.
8503TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8504 // Request focus on an invisible mirror.
8505 mWindow->setVisible(false);
8506 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008507 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008508 setFocusedWindow(mMirror);
8509
8510 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008512 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8513 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008514
8515 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008516 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008517
8518 // window gets focused
8519 mWindow->consumeFocusEvent(true);
8520 // window gets the pending key event
8521 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8522}
Prabir Pradhan99987712020-11-10 18:43:05 -08008523
8524class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8525protected:
8526 std::shared_ptr<FakeApplicationHandle> mApp;
8527 sp<FakeWindowHandle> mWindow;
8528 sp<FakeWindowHandle> mSecondWindow;
8529
8530 void SetUp() override {
8531 InputDispatcherTest::SetUp();
8532 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008533 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008534 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008535 mSecondWindow =
8536 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008537 mSecondWindow->setFocusable(true);
8538
8539 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008540 mDispatcher->onWindowInfosChanged(
8541 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008542
8543 setFocusedWindow(mWindow);
8544 mWindow->consumeFocusEvent(true);
8545 }
8546
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008547 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008548 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008549 }
8550
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008551 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8552 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008553 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008554 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8555 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008556 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008557 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008558 }
8559};
8560
8561TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8562 // Ensure that capture cannot be obtained for unfocused windows.
8563 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8564 mFakePolicy->assertSetPointerCaptureNotCalled();
8565 mSecondWindow->assertNoEvents();
8566
8567 // Ensure that capture can be enabled from the focus window.
8568 requestAndVerifyPointerCapture(mWindow, true);
8569
8570 // Ensure that capture cannot be disabled from a window that does not have capture.
8571 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8572 mFakePolicy->assertSetPointerCaptureNotCalled();
8573
8574 // Ensure that capture can be disabled from the window with capture.
8575 requestAndVerifyPointerCapture(mWindow, false);
8576}
8577
8578TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008579 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008580
8581 setFocusedWindow(mSecondWindow);
8582
8583 // Ensure that the capture disabled event was sent first.
8584 mWindow->consumeCaptureEvent(false);
8585 mWindow->consumeFocusEvent(false);
8586 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008587 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008588
8589 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008590 notifyPointerCaptureChanged({});
8591 notifyPointerCaptureChanged(request);
8592 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008593 mWindow->assertNoEvents();
8594 mSecondWindow->assertNoEvents();
8595 mFakePolicy->assertSetPointerCaptureNotCalled();
8596}
8597
8598TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008599 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008600
8601 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008602 notifyPointerCaptureChanged({});
8603 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008604
8605 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008606 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008607 mWindow->consumeCaptureEvent(false);
8608 mWindow->assertNoEvents();
8609}
8610
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008611TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8612 requestAndVerifyPointerCapture(mWindow, true);
8613
8614 // The first window loses focus.
8615 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008616 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008617 mWindow->consumeCaptureEvent(false);
8618
8619 // Request Pointer Capture from the second window before the notification from InputReader
8620 // arrives.
8621 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008622 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008623
8624 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008625 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008626
8627 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008628 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008629
8630 mSecondWindow->consumeFocusEvent(true);
8631 mSecondWindow->consumeCaptureEvent(true);
8632}
8633
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008634TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8635 // App repeatedly enables and disables capture.
8636 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8637 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8638 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8639 mFakePolicy->assertSetPointerCaptureCalled(false);
8640 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8641 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8642
8643 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8644 // first request is now stale, this should do nothing.
8645 notifyPointerCaptureChanged(firstRequest);
8646 mWindow->assertNoEvents();
8647
8648 // InputReader notifies that the second request was enabled.
8649 notifyPointerCaptureChanged(secondRequest);
8650 mWindow->consumeCaptureEvent(true);
8651}
8652
Prabir Pradhan7092e262022-05-03 16:51:09 +00008653TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8654 requestAndVerifyPointerCapture(mWindow, true);
8655
8656 // App toggles pointer capture off and on.
8657 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8658 mFakePolicy->assertSetPointerCaptureCalled(false);
8659
8660 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8661 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8662
8663 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8664 // preceding "disable" request.
8665 notifyPointerCaptureChanged(enableRequest);
8666
8667 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8668 // any notifications.
8669 mWindow->assertNoEvents();
8670}
8671
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008672/**
8673 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8674 * mouse movements don't affect the previous mouse hovering state.
8675 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8676 * HOVER_MOVE events).
8677 */
8678TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8679 // Mouse hover on the window
8680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8681 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8682 .build());
8683 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8684 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8685 .build());
8686
8687 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8688 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8689
8690 // Start pointer capture
8691 requestAndVerifyPointerCapture(mWindow, true);
8692
8693 // Send some relative mouse movements and receive them in the window.
8694 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8695 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8696 .build());
8697 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8698 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8699
8700 // Stop pointer capture
8701 requestAndVerifyPointerCapture(mWindow, false);
8702
8703 // Continue hovering on the window
8704 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8705 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8706 .build());
8707 mWindow->consumeMotionEvent(
8708 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8709
8710 mWindow->assertNoEvents();
8711}
8712
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008713class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8714protected:
8715 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008716
8717 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8718 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8719
8720 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8721 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8722
8723 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8724 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8725 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8726 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8727 MAXIMUM_OBSCURING_OPACITY);
8728
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008729 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8730 static constexpr gui::Uid APP_B_UID{10002};
8731 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008732
8733 sp<FakeWindowHandle> mTouchWindow;
8734
8735 virtual void SetUp() override {
8736 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008737 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008738 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8739 }
8740
8741 virtual void TearDown() override {
8742 InputDispatcherTest::TearDown();
8743 mTouchWindow.clear();
8744 }
8745
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008746 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008747 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008748 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008749 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008750 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008751 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008752 return window;
8753 }
8754
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008755 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008756 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8757 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008758 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008759 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008760 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008761 return window;
8762 }
8763
8764 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008765 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8766 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8767 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008768 }
8769};
8770
8771TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008772 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008773 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008774 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008775
8776 touch();
8777
8778 mTouchWindow->assertNoEvents();
8779}
8780
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008781TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008782 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8783 const sp<FakeWindowHandle>& w =
8784 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008785 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008786
8787 touch();
8788
8789 mTouchWindow->assertNoEvents();
8790}
8791
8792TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008793 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8794 const sp<FakeWindowHandle>& w =
8795 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008796 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008797
8798 touch();
8799
8800 w->assertNoEvents();
8801}
8802
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008803TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008804 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008805 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008806
8807 touch();
8808
8809 mTouchWindow->consumeAnyMotionDown();
8810}
8811
8812TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008813 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008814 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008815 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008817
8818 touch({PointF{100, 100}});
8819
8820 mTouchWindow->consumeAnyMotionDown();
8821}
8822
8823TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008824 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008825 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008826 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008827
8828 touch();
8829
8830 mTouchWindow->consumeAnyMotionDown();
8831}
8832
8833TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8834 const sp<FakeWindowHandle>& w =
8835 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008836 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008837
8838 touch();
8839
8840 mTouchWindow->consumeAnyMotionDown();
8841}
8842
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008843TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8844 const sp<FakeWindowHandle>& w =
8845 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008846 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008847
8848 touch();
8849
8850 w->assertNoEvents();
8851}
8852
8853/**
8854 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8855 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8856 * window, the occluding window will still receive ACTION_OUTSIDE event.
8857 */
8858TEST_F(InputDispatcherUntrustedTouchesTest,
8859 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8860 const sp<FakeWindowHandle>& w =
8861 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008862 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008863 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008864
8865 touch();
8866
8867 w->consumeMotionOutside();
8868}
8869
8870TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8871 const sp<FakeWindowHandle>& w =
8872 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008873 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008874 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008875
8876 touch();
8877
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008878 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008879}
8880
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008881TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008882 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008883 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8884 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008885 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008886
8887 touch();
8888
8889 mTouchWindow->consumeAnyMotionDown();
8890}
8891
8892TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8893 const sp<FakeWindowHandle>& w =
8894 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8895 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008896 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008897
8898 touch();
8899
8900 mTouchWindow->consumeAnyMotionDown();
8901}
8902
8903TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008904 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008905 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8906 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008907 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008908
8909 touch();
8910
8911 mTouchWindow->assertNoEvents();
8912}
8913
8914TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8915 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8916 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008917 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8918 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008919 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008920 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8921 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008922 mDispatcher->onWindowInfosChanged(
8923 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008924
8925 touch();
8926
8927 mTouchWindow->assertNoEvents();
8928}
8929
8930TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8931 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8932 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008933 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8934 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008935 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008936 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8937 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008938 mDispatcher->onWindowInfosChanged(
8939 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008940
8941 touch();
8942
8943 mTouchWindow->consumeAnyMotionDown();
8944}
8945
8946TEST_F(InputDispatcherUntrustedTouchesTest,
8947 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8948 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008949 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8950 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008951 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008952 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8953 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008954 mDispatcher->onWindowInfosChanged(
8955 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008956
8957 touch();
8958
8959 mTouchWindow->consumeAnyMotionDown();
8960}
8961
8962TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8963 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008964 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8965 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008966 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008967 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8968 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008969 mDispatcher->onWindowInfosChanged(
8970 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008971
8972 touch();
8973
8974 mTouchWindow->assertNoEvents();
8975}
8976
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008977TEST_F(InputDispatcherUntrustedTouchesTest,
8978 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8979 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008980 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8981 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008982 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008983 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8984 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008985 mDispatcher->onWindowInfosChanged(
8986 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008987
8988 touch();
8989
8990 mTouchWindow->assertNoEvents();
8991}
8992
8993TEST_F(InputDispatcherUntrustedTouchesTest,
8994 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8995 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008996 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8997 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008998 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008999 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9000 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009001 mDispatcher->onWindowInfosChanged(
9002 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009003
9004 touch();
9005
9006 mTouchWindow->consumeAnyMotionDown();
9007}
9008
9009TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9010 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009011 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9012 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009013 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009014
9015 touch();
9016
9017 mTouchWindow->consumeAnyMotionDown();
9018}
9019
9020TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9021 const sp<FakeWindowHandle>& w =
9022 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009023 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009024
9025 touch();
9026
9027 mTouchWindow->consumeAnyMotionDown();
9028}
9029
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009030TEST_F(InputDispatcherUntrustedTouchesTest,
9031 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9032 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9033 const sp<FakeWindowHandle>& w =
9034 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009035 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009036
9037 touch();
9038
9039 mTouchWindow->assertNoEvents();
9040}
9041
9042TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9043 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9044 const sp<FakeWindowHandle>& w =
9045 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009046 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009047
9048 touch();
9049
9050 mTouchWindow->consumeAnyMotionDown();
9051}
9052
9053TEST_F(InputDispatcherUntrustedTouchesTest,
9054 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9055 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9056 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009057 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9058 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009059 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009060
9061 touch();
9062
9063 mTouchWindow->consumeAnyMotionDown();
9064}
9065
9066TEST_F(InputDispatcherUntrustedTouchesTest,
9067 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9068 const sp<FakeWindowHandle>& w1 =
9069 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9070 OPACITY_BELOW_THRESHOLD);
9071 const sp<FakeWindowHandle>& w2 =
9072 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9073 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009074 mDispatcher->onWindowInfosChanged(
9075 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009076
9077 touch();
9078
9079 mTouchWindow->assertNoEvents();
9080}
9081
9082/**
9083 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9084 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9085 * (which alone would result in allowing touches) does not affect the blocking behavior.
9086 */
9087TEST_F(InputDispatcherUntrustedTouchesTest,
9088 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9089 const sp<FakeWindowHandle>& wB =
9090 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9091 OPACITY_BELOW_THRESHOLD);
9092 const sp<FakeWindowHandle>& wC =
9093 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9094 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009095 mDispatcher->onWindowInfosChanged(
9096 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009097
9098 touch();
9099
9100 mTouchWindow->assertNoEvents();
9101}
9102
9103/**
9104 * This test is testing that a window from a different UID but with same application token doesn't
9105 * block the touch. Apps can share the application token for close UI collaboration for example.
9106 */
9107TEST_F(InputDispatcherUntrustedTouchesTest,
9108 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9109 const sp<FakeWindowHandle>& w =
9110 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9111 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009112 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009113
9114 touch();
9115
9116 mTouchWindow->consumeAnyMotionDown();
9117}
9118
arthurhungb89ccb02020-12-30 16:19:01 +08009119class InputDispatcherDragTests : public InputDispatcherTest {
9120protected:
9121 std::shared_ptr<FakeApplicationHandle> mApp;
9122 sp<FakeWindowHandle> mWindow;
9123 sp<FakeWindowHandle> mSecondWindow;
9124 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009125 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009126 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9127 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009128
9129 void SetUp() override {
9130 InputDispatcherTest::SetUp();
9131 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009132 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009133 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009134
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009135 mSecondWindow =
9136 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009137 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009138
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009139 mSpyWindow =
9140 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009141 mSpyWindow->setSpy(true);
9142 mSpyWindow->setTrustedOverlay(true);
9143 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9144
arthurhungb89ccb02020-12-30 16:19:01 +08009145 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009146 mDispatcher->onWindowInfosChanged(
9147 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9148 {},
9149 0,
9150 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009151 }
9152
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009153 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9154 switch (fromSource) {
9155 case AINPUT_SOURCE_TOUCHSCREEN:
9156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009157 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009158 ADISPLAY_ID_DEFAULT, {50, 50}))
9159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9160 break;
9161 case AINPUT_SOURCE_STYLUS:
9162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009163 injectMotionEvent(*mDispatcher,
9164 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9165 AINPUT_SOURCE_STYLUS)
9166 .buttonState(
9167 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9168 .pointer(PointerBuilder(0, ToolType::STYLUS)
9169 .x(50)
9170 .y(50))
9171 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009172 break;
9173 case AINPUT_SOURCE_MOUSE:
9174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009175 injectMotionEvent(*mDispatcher,
9176 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9177 AINPUT_SOURCE_MOUSE)
9178 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9179 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9180 ToolType::MOUSE)
9181 .x(50)
9182 .y(50))
9183 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009184 break;
9185 default:
9186 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9187 }
arthurhungb89ccb02020-12-30 16:19:01 +08009188
9189 // Window should receive motion event.
9190 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009191 // Spy window should also receive motion event
9192 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009193 }
9194
9195 // Start performing drag, we will create a drag window and transfer touch to it.
9196 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9197 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009198 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009199 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009200 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009201 }
arthurhungb89ccb02020-12-30 16:19:01 +08009202
9203 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009204 mDragWindow =
9205 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009206 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009207 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9208 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9209 {},
9210 0,
9211 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009212
9213 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009214 bool transferred =
9215 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009216 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009217 if (transferred) {
9218 mWindow->consumeMotionCancel();
9219 mDragWindow->consumeMotionDown();
9220 }
9221 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009222 }
9223};
9224
9225TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009226 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009227
9228 // Move on window.
9229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009230 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009231 ADISPLAY_ID_DEFAULT, {50, 50}))
9232 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9233 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9234 mWindow->consumeDragEvent(false, 50, 50);
9235 mSecondWindow->assertNoEvents();
9236
9237 // Move to another window.
9238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009239 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009240 ADISPLAY_ID_DEFAULT, {150, 50}))
9241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9242 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9243 mWindow->consumeDragEvent(true, 150, 50);
9244 mSecondWindow->consumeDragEvent(false, 50, 50);
9245
9246 // Move back to original window.
9247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009248 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009249 ADISPLAY_ID_DEFAULT, {50, 50}))
9250 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9251 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9252 mWindow->consumeDragEvent(false, 50, 50);
9253 mSecondWindow->consumeDragEvent(true, -50, 50);
9254
9255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009256 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9257 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009258 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9259 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9260 mWindow->assertNoEvents();
9261 mSecondWindow->assertNoEvents();
9262}
9263
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009264TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009265 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009266
9267 // No cancel event after drag start
9268 mSpyWindow->assertNoEvents();
9269
9270 const MotionEvent secondFingerDownEvent =
9271 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9272 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009273 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9274 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009275 .build();
9276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009277 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009278 InputEventInjectionSync::WAIT_FOR_RESULT))
9279 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9280
9281 // Receives cancel for first pointer after next pointer down
9282 mSpyWindow->consumeMotionCancel();
9283 mSpyWindow->consumeMotionDown();
9284
9285 mSpyWindow->assertNoEvents();
9286}
9287
arthurhungf452d0b2021-01-06 00:19:52 +08009288TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009289 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009290
9291 // Move on window.
9292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009293 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009294 ADISPLAY_ID_DEFAULT, {50, 50}))
9295 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9296 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9297 mWindow->consumeDragEvent(false, 50, 50);
9298 mSecondWindow->assertNoEvents();
9299
9300 // Move to another window.
9301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009302 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009303 ADISPLAY_ID_DEFAULT, {150, 50}))
9304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9305 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9306 mWindow->consumeDragEvent(true, 150, 50);
9307 mSecondWindow->consumeDragEvent(false, 50, 50);
9308
9309 // drop to another window.
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009311 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009312 {150, 50}))
9313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9314 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009315 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009316 mWindow->assertNoEvents();
9317 mSecondWindow->assertNoEvents();
9318}
9319
arthurhung6d4bed92021-03-17 11:59:33 +08009320TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009321 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009322
9323 // Move on window and keep button pressed.
9324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009325 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009326 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9327 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009328 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009329 .build()))
9330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9331 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9332 mWindow->consumeDragEvent(false, 50, 50);
9333 mSecondWindow->assertNoEvents();
9334
9335 // Move to another window and release button, expect to drop item.
9336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009337 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009338 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9339 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009340 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009341 .build()))
9342 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9343 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9344 mWindow->assertNoEvents();
9345 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009346 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009347
9348 // nothing to the window.
9349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009350 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009351 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9352 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009353 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009354 .build()))
9355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9356 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9357 mWindow->assertNoEvents();
9358 mSecondWindow->assertNoEvents();
9359}
9360
Arthur Hung54745652022-04-20 07:17:41 +00009361TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009362 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009363
9364 // Set second window invisible.
9365 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009366 mDispatcher->onWindowInfosChanged(
9367 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009368
9369 // Move on window.
9370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009371 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009372 ADISPLAY_ID_DEFAULT, {50, 50}))
9373 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9374 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9375 mWindow->consumeDragEvent(false, 50, 50);
9376 mSecondWindow->assertNoEvents();
9377
9378 // Move to another window.
9379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009380 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009381 ADISPLAY_ID_DEFAULT, {150, 50}))
9382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9383 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9384 mWindow->consumeDragEvent(true, 150, 50);
9385 mSecondWindow->assertNoEvents();
9386
9387 // drop to another window.
9388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009389 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009390 {150, 50}))
9391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9392 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009393 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009394 mWindow->assertNoEvents();
9395 mSecondWindow->assertNoEvents();
9396}
9397
Arthur Hung54745652022-04-20 07:17:41 +00009398TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009399 // Ensure window could track pointerIds if it didn't support split touch.
9400 mWindow->setPreventSplitting(true);
9401
Arthur Hung54745652022-04-20 07:17:41 +00009402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009403 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009404 {50, 50}))
9405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9406 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9407
9408 const MotionEvent secondFingerDownEvent =
9409 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9410 .displayId(ADISPLAY_ID_DEFAULT)
9411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9413 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009414 .build();
9415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009416 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009417 InputEventInjectionSync::WAIT_FOR_RESULT))
9418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009419 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009420
9421 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009422 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009423}
9424
9425TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9426 // First down on second window.
9427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009428 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009429 {150, 50}))
9430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9431
9432 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9433
9434 // Second down on first window.
9435 const MotionEvent secondFingerDownEvent =
9436 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9437 .displayId(ADISPLAY_ID_DEFAULT)
9438 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009439 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9440 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009441 .build();
9442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009443 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009444 InputEventInjectionSync::WAIT_FOR_RESULT))
9445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9446 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9447
9448 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009449 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009450
9451 // Move on window.
9452 const MotionEvent secondFingerMoveEvent =
9453 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9454 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009455 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9456 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009457 .build();
9458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009459 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009460 InputEventInjectionSync::WAIT_FOR_RESULT));
9461 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9462 mWindow->consumeDragEvent(false, 50, 50);
9463 mSecondWindow->consumeMotionMove();
9464
9465 // Release the drag pointer should perform drop.
9466 const MotionEvent secondFingerUpEvent =
9467 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9468 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009469 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9470 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009471 .build();
9472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009473 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009474 InputEventInjectionSync::WAIT_FOR_RESULT));
9475 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009476 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009477 mWindow->assertNoEvents();
9478 mSecondWindow->consumeMotionMove();
9479}
9480
Arthur Hung3915c1f2022-05-31 07:17:17 +00009481TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009482 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009483
9484 // Update window of second display.
9485 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009486 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009487 mDispatcher->onWindowInfosChanged(
9488 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9489 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9490 {},
9491 0,
9492 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009493
9494 // Let second display has a touch state.
9495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009496 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009497 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9498 AINPUT_SOURCE_TOUCHSCREEN)
9499 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009500 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009501 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009502 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009503 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009504 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009505 mDispatcher->onWindowInfosChanged(
9506 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9507 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9508 {},
9509 0,
9510 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009511
9512 // Move on window.
9513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009514 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009515 ADISPLAY_ID_DEFAULT, {50, 50}))
9516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9517 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9518 mWindow->consumeDragEvent(false, 50, 50);
9519 mSecondWindow->assertNoEvents();
9520
9521 // Move to another window.
9522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009523 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009524 ADISPLAY_ID_DEFAULT, {150, 50}))
9525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9526 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9527 mWindow->consumeDragEvent(true, 150, 50);
9528 mSecondWindow->consumeDragEvent(false, 50, 50);
9529
9530 // drop to another window.
9531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009532 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009533 {150, 50}))
9534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9535 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009536 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009537 mWindow->assertNoEvents();
9538 mSecondWindow->assertNoEvents();
9539}
9540
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009541TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9542 startDrag(true, AINPUT_SOURCE_MOUSE);
9543 // Move on window.
9544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009545 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009546 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9547 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009548 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009549 .x(50)
9550 .y(50))
9551 .build()))
9552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9553 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9554 mWindow->consumeDragEvent(false, 50, 50);
9555 mSecondWindow->assertNoEvents();
9556
9557 // Move to another window.
9558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009559 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009560 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9561 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009562 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009563 .x(150)
9564 .y(50))
9565 .build()))
9566 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9567 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9568 mWindow->consumeDragEvent(true, 150, 50);
9569 mSecondWindow->consumeDragEvent(false, 50, 50);
9570
9571 // drop to another window.
9572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009573 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009574 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9575 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009576 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009577 .x(150)
9578 .y(50))
9579 .build()))
9580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9581 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009582 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009583 mWindow->assertNoEvents();
9584 mSecondWindow->assertNoEvents();
9585}
9586
Linnan Li5af92f92023-07-14 14:36:22 +08009587/**
9588 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9589 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9590 */
9591TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9592 // Down on second window
9593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9594 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9595 {150, 50}))
9596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9597
9598 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9599 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9600
9601 // Down on first window
9602 const MotionEvent secondFingerDownEvent =
9603 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9604 .displayId(ADISPLAY_ID_DEFAULT)
9605 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9606 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9607 .build();
9608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9609 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9610 InputEventInjectionSync::WAIT_FOR_RESULT))
9611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9612 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9613 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9614 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9615
9616 // Start drag on first window
9617 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9618
9619 // Trigger cancel
9620 mDispatcher->cancelCurrentTouch();
9621 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9622 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9623 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9624
9625 ASSERT_TRUE(mDispatcher->waitForIdle());
9626 // The D&D finished with nullptr
9627 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9628
9629 // Remove drag window
9630 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9631
9632 // Inject a simple gesture, ensure dispatcher not crashed
9633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9634 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9635 PointF{50, 50}))
9636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9637 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9638
9639 const MotionEvent moveEvent =
9640 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9641 .displayId(ADISPLAY_ID_DEFAULT)
9642 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9643 .build();
9644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9645 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9646 InputEventInjectionSync::WAIT_FOR_RESULT))
9647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9648 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9649
9650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9651 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9652 {50, 50}))
9653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9654 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9655}
9656
Vishnu Nair062a8672021-09-03 16:07:44 -07009657class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9658
9659TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009661 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9662 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009663 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009664 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9665 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009666 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009667 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009668 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009669
9670 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009671 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009672 window->assertNoEvents();
9673
Prabir Pradhan678438e2023-04-13 19:32:51 +00009674 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9675 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009676 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9677 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009678 window->assertNoEvents();
9679
9680 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009681 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009682 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009683
Prabir Pradhan678438e2023-04-13 19:32:51 +00009684 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009685 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9686
Prabir Pradhan678438e2023-04-13 19:32:51 +00009687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9688 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009689 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9690 window->assertNoEvents();
9691}
9692
9693TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9694 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9695 std::make_shared<FakeApplicationHandle>();
9696 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009697 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9698 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009699 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009700 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009701 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9704 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009705 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009706 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009707 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9708 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009709 mDispatcher->onWindowInfosChanged(
9710 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009711 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009712 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009713
9714 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009715 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009716 window->assertNoEvents();
9717
Prabir Pradhan678438e2023-04-13 19:32:51 +00009718 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9719 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009720 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9721 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009722 window->assertNoEvents();
9723
9724 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009725 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009726 mDispatcher->onWindowInfosChanged(
9727 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009728
Prabir Pradhan678438e2023-04-13 19:32:51 +00009729 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009730 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9731
Prabir Pradhan678438e2023-04-13 19:32:51 +00009732 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9733 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009734 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9735 window->assertNoEvents();
9736}
9737
9738TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9739 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9740 std::make_shared<FakeApplicationHandle>();
9741 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009742 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9743 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009744 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009745 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009746 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9749 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009750 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009751 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009752 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9753 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009754 mDispatcher->onWindowInfosChanged(
9755 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009756 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009757 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009758
9759 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009760 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009761 window->assertNoEvents();
9762
Prabir Pradhan678438e2023-04-13 19:32:51 +00009763 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9764 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009765 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9766 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009767 window->assertNoEvents();
9768
9769 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009770 mDispatcher->onWindowInfosChanged(
9771 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009772
Prabir Pradhan678438e2023-04-13 19:32:51 +00009773 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009774 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9775
Prabir Pradhan678438e2023-04-13 19:32:51 +00009776 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9777 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009778 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9779 window->assertNoEvents();
9780}
9781
Antonio Kantekf16f2832021-09-28 04:39:20 +00009782class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9783protected:
9784 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009785 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009786 sp<FakeWindowHandle> mWindow;
9787 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009788 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009789
9790 void SetUp() override {
9791 InputDispatcherTest::SetUp();
9792
9793 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009794 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009795 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009796 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009797 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009798 mSecondWindow =
9799 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009800 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009801 mThirdWindow =
9802 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9803 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9804 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009805
9806 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009807 mDispatcher->onWindowInfosChanged(
9808 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9809 {},
9810 0,
9811 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009812 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009813 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009814
Antonio Kantek15beb512022-06-13 22:35:41 +00009815 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009816 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009817 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009818 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9819 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009820 mThirdWindow->assertNoEvents();
9821 }
9822
9823 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9824 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009825 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009826 SECOND_DISPLAY_ID)) {
9827 mWindow->assertNoEvents();
9828 mSecondWindow->assertNoEvents();
9829 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009830 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009831 }
9832
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009833 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009834 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009835 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9836 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009837 mWindow->consumeTouchModeEvent(inTouchMode);
9838 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009839 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009840 }
9841};
9842
Antonio Kantek26defcf2022-02-08 01:12:27 +00009843TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009844 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009845 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9846 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009847 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009848}
9849
Antonio Kantek26defcf2022-02-08 01:12:27 +00009850TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9851 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009852 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009853 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009854 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009855 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009856 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009857 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009858 mWindow->assertNoEvents();
9859 mSecondWindow->assertNoEvents();
9860}
9861
9862TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9863 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009864 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009865 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009866 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009867 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009868 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009869}
9870
Antonio Kantekf16f2832021-09-28 04:39:20 +00009871TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009872 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009873 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9874 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009875 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009876 mWindow->assertNoEvents();
9877 mSecondWindow->assertNoEvents();
9878}
9879
Antonio Kantek15beb512022-06-13 22:35:41 +00009880TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9881 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9882 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9883 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009884 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009885 mWindow->assertNoEvents();
9886 mSecondWindow->assertNoEvents();
9887 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9888}
9889
Antonio Kantek48710e42022-03-24 14:19:30 -07009890TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9891 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9893 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009894 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9895 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9896
9897 // Then remove focus.
9898 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009899 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009900
9901 // Assert that caller can switch touch mode by owning one of the last interacted window.
9902 const WindowInfo& windowInfo = *mWindow->getInfo();
9903 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9904 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009905 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009906}
9907
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009908class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9909public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009910 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009911 std::shared_ptr<FakeApplicationHandle> application =
9912 std::make_shared<FakeApplicationHandle>();
9913 std::string name = "Fake Spy ";
9914 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009915 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9916 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009917 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009918 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009919 return spy;
9920 }
9921
9922 sp<FakeWindowHandle> createForeground() {
9923 std::shared_ptr<FakeApplicationHandle> application =
9924 std::make_shared<FakeApplicationHandle>();
9925 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009926 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9927 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009928 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009929 return window;
9930 }
9931
9932private:
9933 int mSpyCount{0};
9934};
9935
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009936using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009937/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009938 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9939 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009940TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009941 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009942 ScopedSilentDeath _silentDeath;
9943
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009944 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009945 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009946 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009947 ".* not a trusted overlay");
9948}
9949
9950/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009951 * Input injection into a display with a spy window but no foreground windows should succeed.
9952 */
9953TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009954 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009955 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009956
9957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009958 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9960 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9961}
9962
9963/**
9964 * Verify the order in which different input windows receive events. The touched foreground window
9965 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9966 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9967 * receive events before ones belows it.
9968 *
9969 * Here, we set up a scenario with four windows in the following Z order from the top:
9970 * spy1, spy2, window, spy3.
9971 * We then inject an event and verify that the foreground "window" receives it first, followed by
9972 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9973 * window.
9974 */
9975TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9976 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009977 auto spy1 = createSpy();
9978 auto spy2 = createSpy();
9979 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009980 mDispatcher->onWindowInfosChanged(
9981 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009982 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9983 const size_t numChannels = channels.size();
9984
Michael Wright8e9a8562022-02-09 13:44:29 +00009985 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009986 if (!epollFd.ok()) {
9987 FAIL() << "Failed to create epoll fd";
9988 }
9989
9990 for (size_t i = 0; i < numChannels; i++) {
9991 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9992 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9993 FAIL() << "Failed to add fd to epoll";
9994 }
9995 }
9996
9997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009998 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10000
10001 std::vector<size_t> eventOrder;
10002 std::vector<struct epoll_event> events(numChannels);
10003 for (;;) {
10004 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10005 (100ms).count());
10006 if (nFds < 0) {
10007 FAIL() << "Failed to call epoll_wait";
10008 }
10009 if (nFds == 0) {
10010 break; // epoll_wait timed out
10011 }
10012 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010013 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010014 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010015 channels[i]->consumeMotionDown();
10016 }
10017 }
10018
10019 // Verify the order in which the events were received.
10020 EXPECT_EQ(3u, eventOrder.size());
10021 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10022 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10023 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10024}
10025
10026/**
10027 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10028 */
10029TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10030 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010031 auto spy = createSpy();
10032 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010033 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010034
10035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010036 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10038 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10039 spy->assertNoEvents();
10040}
10041
10042/**
10043 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10044 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10045 * to the window.
10046 */
10047TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10048 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010049 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010050 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010051 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010052
10053 // Inject an event outside the spy window's touchable region.
10054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10057 window->consumeMotionDown();
10058 spy->assertNoEvents();
10059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010060 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10062 window->consumeMotionUp();
10063 spy->assertNoEvents();
10064
10065 // Inject an event inside the spy window's touchable region.
10066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010067 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010068 {5, 10}))
10069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10070 window->consumeMotionDown();
10071 spy->consumeMotionDown();
10072}
10073
10074/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010075 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010076 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010077 */
10078TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10079 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010080 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010081 auto spy = createSpy();
10082 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010083 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010084 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010085 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010086
10087 // Inject an event outside the spy window's frame and touchable region.
10088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010089 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010090 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010091 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10092 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010093 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010094}
10095
10096/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010097 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10098 * pointers that are down within its bounds.
10099 */
10100TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10101 auto windowLeft = createForeground();
10102 windowLeft->setFrame({0, 0, 100, 200});
10103 auto windowRight = createForeground();
10104 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010105 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010106 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010107 mDispatcher->onWindowInfosChanged(
10108 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010109
10110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010111 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010112 {50, 50}))
10113 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10114 windowLeft->consumeMotionDown();
10115 spy->consumeMotionDown();
10116
10117 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010118 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010119 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010120 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10121 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010122 .build();
10123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010124 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010125 InputEventInjectionSync::WAIT_FOR_RESULT))
10126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10127 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010128 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010129}
10130
10131/**
10132 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10133 * the spy should receive the second pointer with ACTION_DOWN.
10134 */
10135TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10136 auto window = createForeground();
10137 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010138 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010139 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010140 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010141
10142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010143 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010144 {50, 50}))
10145 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10146 window->consumeMotionDown();
10147 spyRight->assertNoEvents();
10148
10149 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010150 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010151 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010152 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10153 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010154 .build();
10155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010156 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010157 InputEventInjectionSync::WAIT_FOR_RESULT))
10158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010159 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010160 spyRight->consumeMotionDown();
10161}
10162
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010163/**
10164 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10165 * windows should be allowed to control split touch.
10166 */
10167TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010168 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010169 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010170 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010171 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010172
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010173 auto window = createForeground();
10174 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010175
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010176 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010177
10178 // First finger down, no window touched.
10179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010180 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010181 {100, 200}))
10182 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10183 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10184 window->assertNoEvents();
10185
10186 // Second finger down on window, the window should receive touch down.
10187 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010188 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010189 .displayId(ADISPLAY_ID_DEFAULT)
10190 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010191 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10192 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010193 .build();
10194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010195 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010196 InputEventInjectionSync::WAIT_FOR_RESULT))
10197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10198
10199 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010200 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010201}
10202
10203/**
10204 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10205 * do not receive key events.
10206 */
10207TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010208 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010209 spy->setFocusable(false);
10210
10211 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010212 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010213 setFocusedWindow(window);
10214 window->consumeFocusEvent(true);
10215
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010217 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10218 window->consumeKeyDown(ADISPLAY_ID_NONE);
10219
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010221 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10222 window->consumeKeyUp(ADISPLAY_ID_NONE);
10223
10224 spy->assertNoEvents();
10225}
10226
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010227using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10228
10229/**
10230 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10231 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10232 */
10233TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10234 auto window = createForeground();
10235 auto spy1 = createSpy();
10236 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010237 mDispatcher->onWindowInfosChanged(
10238 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010239
10240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010241 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010242 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10243 window->consumeMotionDown();
10244 spy1->consumeMotionDown();
10245 spy2->consumeMotionDown();
10246
10247 // Pilfer pointers from the second spy window.
10248 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10249 spy2->assertNoEvents();
10250 spy1->consumeMotionCancel();
10251 window->consumeMotionCancel();
10252
10253 // The rest of the gesture should only be sent to the second spy window.
10254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010255 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010256 ADISPLAY_ID_DEFAULT))
10257 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10258 spy2->consumeMotionMove();
10259 spy1->assertNoEvents();
10260 window->assertNoEvents();
10261}
10262
10263/**
10264 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10265 * in the middle of the gesture.
10266 */
10267TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10268 auto window = createForeground();
10269 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010270 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010271
10272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010273 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10275 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10276 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10277
10278 window->releaseChannel();
10279
10280 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10281
10282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010283 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10285 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10286}
10287
10288/**
10289 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10290 * the spy, but not to any other windows.
10291 */
10292TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10293 auto spy = createSpy();
10294 auto window = createForeground();
10295
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010296 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010297
10298 // First finger down on the window and the spy.
10299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010300 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010301 {100, 200}))
10302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10303 spy->consumeMotionDown();
10304 window->consumeMotionDown();
10305
10306 // Spy window pilfers the pointers.
10307 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10308 window->consumeMotionCancel();
10309
10310 // Second finger down on the window and spy, but the window should not receive the pointer down.
10311 const MotionEvent secondFingerDownEvent =
10312 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10313 .displayId(ADISPLAY_ID_DEFAULT)
10314 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010315 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10316 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010317 .build();
10318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010319 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010320 InputEventInjectionSync::WAIT_FOR_RESULT))
10321 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10322
Harry Cutts33476232023-01-30 19:57:29 +000010323 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010324
10325 // Third finger goes down outside all windows, so injection should fail.
10326 const MotionEvent thirdFingerDownEvent =
10327 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10328 .displayId(ADISPLAY_ID_DEFAULT)
10329 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010330 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10331 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10332 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010333 .build();
10334 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010335 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010336 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010337 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010338
10339 spy->assertNoEvents();
10340 window->assertNoEvents();
10341}
10342
10343/**
10344 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10345 */
10346TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10347 auto spy = createSpy();
10348 spy->setFrame(Rect(0, 0, 100, 100));
10349 auto window = createForeground();
10350 window->setFrame(Rect(0, 0, 200, 200));
10351
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010352 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010353
10354 // First finger down on the window only
10355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010356 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010357 {150, 150}))
10358 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10359 window->consumeMotionDown();
10360
10361 // Second finger down on the spy and window
10362 const MotionEvent secondFingerDownEvent =
10363 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10364 .displayId(ADISPLAY_ID_DEFAULT)
10365 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010366 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10367 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010368 .build();
10369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010370 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010371 InputEventInjectionSync::WAIT_FOR_RESULT))
10372 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10373 spy->consumeMotionDown();
10374 window->consumeMotionPointerDown(1);
10375
10376 // Third finger down on the spy and window
10377 const MotionEvent thirdFingerDownEvent =
10378 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10379 .displayId(ADISPLAY_ID_DEFAULT)
10380 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010381 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10382 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10383 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010384 .build();
10385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010386 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010387 InputEventInjectionSync::WAIT_FOR_RESULT))
10388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10389 spy->consumeMotionPointerDown(1);
10390 window->consumeMotionPointerDown(2);
10391
10392 // Spy window pilfers the pointers.
10393 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010394 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10395 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010396
10397 spy->assertNoEvents();
10398 window->assertNoEvents();
10399}
10400
10401/**
10402 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10403 * other windows should be canceled. If this results in the cancellation of all pointers for some
10404 * window, then that window should receive ACTION_CANCEL.
10405 */
10406TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10407 auto spy = createSpy();
10408 spy->setFrame(Rect(0, 0, 100, 100));
10409 auto window = createForeground();
10410 window->setFrame(Rect(0, 0, 200, 200));
10411
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010412 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010413
10414 // First finger down on both spy and window
10415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010416 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010417 {10, 10}))
10418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10419 window->consumeMotionDown();
10420 spy->consumeMotionDown();
10421
10422 // Second finger down on the spy and window
10423 const MotionEvent secondFingerDownEvent =
10424 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10425 .displayId(ADISPLAY_ID_DEFAULT)
10426 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010427 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10428 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010429 .build();
10430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010431 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010432 InputEventInjectionSync::WAIT_FOR_RESULT))
10433 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10434 spy->consumeMotionPointerDown(1);
10435 window->consumeMotionPointerDown(1);
10436
10437 // Spy window pilfers the pointers.
10438 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10439 window->consumeMotionCancel();
10440
10441 spy->assertNoEvents();
10442 window->assertNoEvents();
10443}
10444
10445/**
10446 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10447 * be sent to other windows
10448 */
10449TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10450 auto spy = createSpy();
10451 spy->setFrame(Rect(0, 0, 100, 100));
10452 auto window = createForeground();
10453 window->setFrame(Rect(0, 0, 200, 200));
10454
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010455 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010456
10457 // First finger down on both window and spy
10458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010459 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010460 {10, 10}))
10461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10462 window->consumeMotionDown();
10463 spy->consumeMotionDown();
10464
10465 // Spy window pilfers the pointers.
10466 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10467 window->consumeMotionCancel();
10468
10469 // Second finger down on the window only
10470 const MotionEvent secondFingerDownEvent =
10471 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10472 .displayId(ADISPLAY_ID_DEFAULT)
10473 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010474 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10475 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010476 .build();
10477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010478 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010479 InputEventInjectionSync::WAIT_FOR_RESULT))
10480 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10481 window->consumeMotionDown();
10482 window->assertNoEvents();
10483
10484 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10485 spy->consumeMotionMove();
10486 spy->assertNoEvents();
10487}
10488
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010489/**
10490 * A window on the left and a window on the right. Also, a spy window that's above all of the
10491 * windows, and spanning both left and right windows.
10492 * Send simultaneous motion streams from two different devices, one to the left window, and another
10493 * to the right window.
10494 * Pilfer from spy window.
10495 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10496 */
10497TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10498 sp<FakeWindowHandle> spy = createSpy();
10499 spy->setFrame(Rect(0, 0, 200, 200));
10500 sp<FakeWindowHandle> leftWindow = createForeground();
10501 leftWindow->setFrame(Rect(0, 0, 100, 100));
10502
10503 sp<FakeWindowHandle> rightWindow = createForeground();
10504 rightWindow->setFrame(Rect(100, 0, 200, 100));
10505
10506 constexpr int32_t stylusDeviceId = 1;
10507 constexpr int32_t touchDeviceId = 2;
10508
10509 mDispatcher->onWindowInfosChanged(
10510 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10511
10512 // Stylus down on left window and spy
10513 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10514 .deviceId(stylusDeviceId)
10515 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10516 .build());
10517 leftWindow->consumeMotionEvent(
10518 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10519 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10520
10521 // Finger down on right window and spy - but spy already has stylus
10522 mDispatcher->notifyMotion(
10523 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10524 .deviceId(touchDeviceId)
10525 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10526 .build());
10527 rightWindow->consumeMotionEvent(
10528 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010529 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010530
10531 // Act: pilfer from spy. Spy is currently receiving touch events.
10532 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010533 leftWindow->consumeMotionEvent(
10534 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010535 rightWindow->consumeMotionEvent(
10536 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10537
10538 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10539 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10540 .deviceId(stylusDeviceId)
10541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10542 .build());
10543 mDispatcher->notifyMotion(
10544 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10545 .deviceId(touchDeviceId)
10546 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10547 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010548 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010549
10550 spy->assertNoEvents();
10551 leftWindow->assertNoEvents();
10552 rightWindow->assertNoEvents();
10553}
10554
Prabir Pradhand65552b2021-10-07 11:23:50 -070010555class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10556public:
10557 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10558 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10559 std::make_shared<FakeApplicationHandle>();
10560 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010561 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10562 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010563 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010564 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010565 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010566 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010567 overlay->setTrustedOverlay(true);
10568
10569 std::shared_ptr<FakeApplicationHandle> application =
10570 std::make_shared<FakeApplicationHandle>();
10571 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010572 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10573 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010574 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010575 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010576
10577 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010578 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010579 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010580 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010581 return {std::move(overlay), std::move(window)};
10582 }
10583
10584 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010585 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010586 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010587 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010588 }
10589
10590 void sendStylusEvent(int32_t action) {
10591 NotifyMotionArgs motionArgs =
10592 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10593 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010594 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010595 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010596 }
10597};
10598
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010599using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10600
10601TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010602 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010603 ScopedSilentDeath _silentDeath;
10604
Prabir Pradhand65552b2021-10-07 11:23:50 -070010605 auto [overlay, window] = setupStylusOverlayScenario();
10606 overlay->setTrustedOverlay(false);
10607 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010608 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10609 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010610 ".* not a trusted overlay");
10611}
10612
10613TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10614 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010615 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010616
10617 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10618 overlay->consumeMotionDown();
10619 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10620 overlay->consumeMotionUp();
10621
10622 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10623 window->consumeMotionDown();
10624 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10625 window->consumeMotionUp();
10626
10627 overlay->assertNoEvents();
10628 window->assertNoEvents();
10629}
10630
10631TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10632 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010633 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010634 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010635
10636 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10637 overlay->consumeMotionDown();
10638 window->consumeMotionDown();
10639 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10640 overlay->consumeMotionUp();
10641 window->consumeMotionUp();
10642
10643 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10644 window->consumeMotionDown();
10645 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10646 window->consumeMotionUp();
10647
10648 overlay->assertNoEvents();
10649 window->assertNoEvents();
10650}
10651
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010652/**
10653 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10654 * The scenario is as follows:
10655 * - The stylus interceptor overlay is configured as a spy window.
10656 * - The stylus interceptor spy receives the start of a new stylus gesture.
10657 * - It pilfers pointers and then configures itself to no longer be a spy.
10658 * - The stylus interceptor continues to receive the rest of the gesture.
10659 */
10660TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10661 auto [overlay, window] = setupStylusOverlayScenario();
10662 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010663 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010664
10665 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10666 overlay->consumeMotionDown();
10667 window->consumeMotionDown();
10668
10669 // The interceptor pilfers the pointers.
10670 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10671 window->consumeMotionCancel();
10672
10673 // The interceptor configures itself so that it is no longer a spy.
10674 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010675 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010676
10677 // It continues to receive the rest of the stylus gesture.
10678 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10679 overlay->consumeMotionMove();
10680 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10681 overlay->consumeMotionUp();
10682
10683 window->assertNoEvents();
10684}
10685
Prabir Pradhan5735a322022-04-11 17:23:34 +000010686struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010687 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010688 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010689 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10690 std::unique_ptr<InputDispatcher>& mDispatcher;
10691
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010692 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010693 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10694
10695 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010696 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010697 ADISPLAY_ID_DEFAULT, {100, 200},
10698 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10699 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10700 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10701 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10702 }
10703
10704 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010705 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010706 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010707 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010708 mPolicyFlags);
10709 }
10710
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010711 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010712 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10713 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10715 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010716 window->setOwnerInfo(mPid, mUid);
10717 return window;
10718 }
10719};
10720
10721using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10722
10723TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010724 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010725 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010726 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010727
10728 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10729 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10730 window->consumeMotionDown();
10731
10732 setFocusedWindow(window);
10733 window->consumeFocusEvent(true);
10734
10735 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10736 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10737 window->consumeKeyDown(ADISPLAY_ID_NONE);
10738}
10739
10740TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010741 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010742 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010743 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010744
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010745 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010746 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10747 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10748
10749 setFocusedWindow(window);
10750 window->consumeFocusEvent(true);
10751
10752 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10753 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10754 window->assertNoEvents();
10755}
10756
10757TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010758 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010759 auto window = owner.createWindow("Owned window");
10760 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010761 spy->setSpy(true);
10762 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010763 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010764
10765 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10766 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10767 spy->consumeMotionDown();
10768 window->consumeMotionDown();
10769}
10770
10771TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010772 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010773 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010774
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010775 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010776 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010777 randosSpy->setSpy(true);
10778 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010779 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010780
10781 // The event is targeted at owner's window, so injection should succeed, but the spy should
10782 // not receive the event.
10783 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10784 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10785 randosSpy->assertNoEvents();
10786 window->consumeMotionDown();
10787}
10788
10789TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010790 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010791 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010792
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010793 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010794 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010795 randosSpy->setSpy(true);
10796 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010797 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010798
10799 // A user that has injection permission can inject into any window.
10800 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010801 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010802 ADISPLAY_ID_DEFAULT));
10803 randosSpy->consumeMotionDown();
10804 window->consumeMotionDown();
10805
10806 setFocusedWindow(randosSpy);
10807 randosSpy->consumeFocusEvent(true);
10808
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010809 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010810 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10811 window->assertNoEvents();
10812}
10813
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010814TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010815 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010816 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010817
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010818 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010819 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010820 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10821 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010822 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010823
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010824 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010825 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10826 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10827 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010828 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010829}
10830
Garfield Tane84e6f92019-08-29 17:28:41 -070010831} // namespace android::inputdispatcher