blob: 606dd6d14f6d63dba49beb6626928e4842efc73f [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 Vishniakoub237f9e2023-07-21 16:42:23 -0700115/**
116 * If we expect to receive the event, the timeout can be made very long. When the test are running
117 * correctly, we will actually never wait until the end of the timeout because the wait will end
118 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
119 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
120 * developer can see the failure quickly (on human scale).
121 */
122static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
123/**
124 * When no event is expected, we can have a very short timeout. A large value here would slow down
125 * the tests. In the unlikely event of system being too slow, the event may still be present but the
126 * timeout would complete before it is consumed. This would result in test flakiness. If this
127 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
128 * would get noticed and addressed quickly.
129 */
130static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
131
Arthur Hungc539dbb2022-12-08 07:45:36 +0000132static constexpr int expectedWallpaperFlags =
133 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
134
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800135using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
136
Gang Wang342c9272020-01-13 13:15:04 -0500137/**
138 * Return a DOWN key event with KEYCODE_A.
139 */
140static KeyEvent getTestKeyEvent() {
141 KeyEvent event;
142
Garfield Tanfbe732e2020-01-24 11:26:14 -0800143 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
144 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
145 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500146 return event;
147}
148
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149// --- FakeInputDispatcherPolicy ---
150
151class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000152 struct AnrResult {
153 sp<IBinder> token{};
154 gui::Pid pid{gui::Pid::INVALID};
155 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800156
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000158 FakeInputDispatcherPolicy() = default;
159 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800160
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800161 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700162 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700163 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700164 EXPECT_EQ(event.getDisplayId(), args.displayId);
165
166 const auto& keyEvent = static_cast<const KeyEvent&>(event);
167 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
168 EXPECT_EQ(keyEvent.getAction(), args.action);
169 });
Jackal Guof9696682018-10-05 12:23:23 +0800170 }
171
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700172 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
173 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700174 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 EXPECT_EQ(event.getDisplayId(), args.displayId);
176
177 const auto& motionEvent = static_cast<const MotionEvent&>(event);
178 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
179 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000180 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
181 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
182 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
183 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700184 });
Jackal Guof9696682018-10-05 12:23:23 +0800185 }
186
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700187 void assertFilterInputEventWasNotCalled() {
188 std::scoped_lock lock(mLock);
189 ASSERT_EQ(nullptr, mFilteredEvent);
190 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800192 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700193 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800194 ASSERT_TRUE(mConfigurationChangedTime)
195 << "Timed out waiting for configuration changed call";
196 ASSERT_EQ(*mConfigurationChangedTime, when);
197 mConfigurationChangedTime = std::nullopt;
198 }
199
200 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700201 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800202 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800203 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800204 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
205 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
206 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
207 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
208 mLastNotifySwitch = std::nullopt;
209 }
210
chaviwfd6d3512019-03-25 13:23:49 -0700211 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700212 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800213 ASSERT_EQ(touchedToken, mOnPointerDownToken);
214 mOnPointerDownToken.clear();
215 }
216
217 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700218 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800219 ASSERT_TRUE(mOnPointerDownToken == nullptr)
220 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700221 }
222
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700223 // This function must be called soon after the expected ANR timer starts,
224 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500225 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700226 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500227 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800228 std::unique_lock lock(mLock);
229 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 ASSERT_NO_FATAL_FAILURE(
232 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700234 }
235
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000236 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800237 const sp<WindowInfoHandle>& window) {
238 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
239 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
240 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500241 }
242
Prabir Pradhanedd96402022-02-15 01:46:16 -0800243 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
244 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000245 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 std::unique_lock lock(mLock);
247 android::base::ScopedLockAssertion assumeLocked(mLock);
248 AnrResult result;
249 ASSERT_NO_FATAL_FAILURE(result =
250 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000251 ASSERT_EQ(expectedToken, result.token);
252 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500253 }
254
Prabir Pradhanedd96402022-02-15 01:46:16 -0800255 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000256 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500257 std::unique_lock lock(mLock);
258 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800259 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
260 const auto& [token, _] = result;
261 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000262 }
263
Prabir Pradhanedd96402022-02-15 01:46:16 -0800264 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000265 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800266 std::unique_lock lock(mLock);
267 android::base::ScopedLockAssertion assumeLocked(mLock);
268 AnrResult result;
269 ASSERT_NO_FATAL_FAILURE(
270 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000271 ASSERT_EQ(expectedToken, result.token);
272 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 }
274
275 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000276 sp<IBinder> getResponsiveWindowToken() {
277 std::unique_lock lock(mLock);
278 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800279 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
280 const auto& [token, _] = result;
281 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700282 }
283
284 void assertNotifyAnrWasNotCalled() {
285 std::scoped_lock lock(mLock);
286 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_TRUE(mAnrWindows.empty());
288 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 << "ANR was not called, but please also consume the 'connection is responsive' "
290 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700291 }
292
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000293 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800294 std::unique_lock lock(mLock);
295 base::ScopedLockAssertion assumeLocked(mLock);
296
297 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
298 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000299 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800300 enabled;
301 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
303 << ") to be called.";
304 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800305 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000306 auto request = *mPointerCaptureRequest;
307 mPointerCaptureRequest.reset();
308 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800309 }
310
311 void assertSetPointerCaptureNotCalled() {
312 std::unique_lock lock(mLock);
313 base::ScopedLockAssertion assumeLocked(mLock);
314
315 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000316 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800317 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000318 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800319 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000320 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800321 }
322
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700323 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
324 const sp<IBinder>& targetToken) {
325 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800326 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800327 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800328 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800329 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800330 }
331
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800332 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
333 std::unique_lock lock(mLock);
334 base::ScopedLockAssertion assumeLocked(mLock);
335 std::optional<sp<IBinder>> receivedToken =
336 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
337 mNotifyInputChannelBroken);
338 ASSERT_TRUE(receivedToken.has_value());
339 ASSERT_EQ(token, *receivedToken);
340 }
341
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800342 /**
343 * Set policy timeout. A value of zero means next key will not be intercepted.
344 */
345 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
346 mInterceptKeyTimeout = timeout;
347 }
348
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700349 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
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
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700394 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
395
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000396 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000397
Prabir Pradhanedd96402022-02-15 01:46:16 -0800398 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
399 // for a specific container to become non-empty. When the container is non-empty, return the
400 // first entry from the container and erase it.
401 template <class T>
402 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
403 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
404 // If there is an ANR, Dispatcher won't be idle because there are still events
405 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
406 // before checking if ANR was called.
407 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
408 // to provide it some time to act. 100ms seems reasonable.
409 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
410 const std::chrono::time_point start = std::chrono::steady_clock::now();
411 std::optional<T> token =
412 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
413 if (!token.has_value()) {
414 ADD_FAILURE() << "Did not receive the ANR callback";
415 return {};
416 }
417
418 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
419 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
420 // the dispatcher started counting before this function was called
421 if (std::chrono::abs(timeout - waited) > 100ms) {
422 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
423 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
424 << "ms, but waited "
425 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
426 << "ms instead";
427 }
428 return *token;
429 }
430
431 template <class T>
432 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
433 std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock,
435 std::condition_variable& condition)
436 REQUIRES(mLock) {
437 condition.wait_for(lock, timeout,
438 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
439 if (storage.empty()) {
440 ADD_FAILURE() << "Did not receive the expected callback";
441 return std::nullopt;
442 }
443 T item = storage.front();
444 storage.pop();
445 return std::make_optional(item);
446 }
447
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600448 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700449 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800450 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800451 }
452
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000453 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800454 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700455 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800456 ASSERT_TRUE(pid.has_value());
457 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700458 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500459 }
460
Prabir Pradhanedd96402022-02-15 01:46:16 -0800461 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000462 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500463 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800464 ASSERT_TRUE(pid.has_value());
465 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500466 mNotifyAnr.notify_all();
467 }
468
469 void notifyNoFocusedWindowAnr(
470 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
471 std::scoped_lock lock(mLock);
472 mAnrApplications.push(applicationHandle);
473 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800474 }
475
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800476 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
477 std::scoped_lock lock(mLock);
478 mBrokenInputChannels.push(connectionToken);
479 mNotifyInputChannelBroken.notify_all();
480 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600482 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700483
Chris Yef59a2f42020-10-16 12:55:26 -0700484 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
485 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
486 const std::vector<float>& values) override {}
487
488 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
489 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000490
Chris Yefb552902021-02-03 17:18:37 -0800491 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
492
Prabir Pradhana41d2442023-04-20 21:30:40 +0000493 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700494 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000495 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700496 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000497 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
498 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800499 break;
500 }
501
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700502 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000503 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
504 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800505 break;
506 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700507 default: {
508 ADD_FAILURE() << "Should only filter keys or motions";
509 break;
510 }
Jackal Guof9696682018-10-05 12:23:23 +0800511 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512 return true;
513 }
514
Prabir Pradhana41d2442023-04-20 21:30:40 +0000515 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
516 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800517 // Clear intercept state when we handled the event.
518 mInterceptKeyTimeout = 0ms;
519 }
520 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600522 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800523
Prabir Pradhana41d2442023-04-20 21:30:40 +0000524 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800525 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
526 // Clear intercept state so we could dispatch the event in next wake.
527 mInterceptKeyTimeout = 0ms;
528 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529 }
530
Prabir Pradhana41d2442023-04-20 21:30:40 +0000531 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
532 uint32_t) override {
533 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800534 }
535
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600536 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
537 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700538 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800539 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
540 * essentially a passthrough for notifySwitch.
541 */
Harry Cutts33476232023-01-30 19:57:29 +0000542 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 }
544
Josep del Riob3981622023-04-18 15:49:45 +0000545 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
546 std::scoped_lock lock(mLock);
547 mPokedUserActivity = true;
548 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800549
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700550 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
551 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
552 }
553
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600554 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700555 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700556 mOnPointerDownToken = newToken;
557 }
558
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000559 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800560 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000561 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800562 mPointerCaptureChangedCondition.notify_all();
563 }
564
arthurhungf452d0b2021-01-06 00:19:52 +0800565 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
566 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800567 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800568 mDropTargetWindowToken = token;
569 }
570
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000571 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000572 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000573 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
574 }
575
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700576 void assertFilterInputEventWasCalledInternal(
577 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700578 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800579 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700580 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800581 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700584} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586// --- InputDispatcherTest ---
587
588class InputDispatcherTest : public testing::Test {
589protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000590 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700591 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800592
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000593 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000594 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700595 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
596
Harry Cutts101ee9b2023-07-06 18:04:14 +0000597 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000598 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700599 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800600 }
601
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000602 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700603 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000604 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700605 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700607
608 /**
609 * Used for debugging when writing the test
610 */
611 void dumpDispatcherState() {
612 std::string dump;
613 mDispatcher->dump(dump);
614 std::stringstream ss(dump);
615 std::string to;
616
617 while (std::getline(ss, to, '\n')) {
618 ALOGE("%s", to.c_str());
619 }
620 }
Vishnu Nair958da932020-08-21 17:12:37 -0700621
Chavi Weingarten847e8512023-03-29 00:26:09 +0000622 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700623 FocusRequest request;
624 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000625 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700626 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
627 request.displayId = window->getInfo()->displayId;
628 mDispatcher->setFocusedWindow(request);
629 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800630};
631
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
633 KeyEvent event;
634
635 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800636 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
637 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000638 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600639 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800640 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000641 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000642 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800643 << "Should reject key events with undefined action.";
644
645 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800646 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
647 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600648 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800649 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000650 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000651 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652 << "Should reject key events with ACTION_MULTIPLE.";
653}
654
655TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
656 MotionEvent event;
657 PointerProperties pointerProperties[MAX_POINTERS + 1];
658 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800659 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660 pointerProperties[i].clear();
661 pointerProperties[i].id = i;
662 pointerCoords[i].clear();
663 }
664
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800665 // Some constants commonly used below
666 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
667 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
668 constexpr int32_t metaState = AMETA_NONE;
669 constexpr MotionClassification classification = MotionClassification::NONE;
670
chaviw9eaa22c2020-07-01 16:21:27 -0700671 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800673 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000674 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700675 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700676 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
677 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000678 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800679 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000680 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000681 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800682 << "Should reject motion events with undefined action.";
683
684 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800685 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800686 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
687 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
688 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
689 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000690 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800691 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000692 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000693 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 << "Should reject motion events with pointer down index too large.";
695
Garfield Tanfbe732e2020-01-24 11:26:14 -0800696 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700697 AMOTION_EVENT_ACTION_POINTER_DOWN |
698 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700699 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
700 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700701 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000702 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800703 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000704 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000705 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 << "Should reject motion events with pointer down index too small.";
707
708 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800709 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800710 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
711 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
712 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
713 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000714 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800715 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000716 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000717 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800718 << "Should reject motion events with pointer up index too large.";
719
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700721 AMOTION_EVENT_ACTION_POINTER_UP |
722 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700723 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
724 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700725 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000726 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800727 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000728 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000729 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800730 << "Should reject motion events with pointer up index too small.";
731
732 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800733 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
734 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700735 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700736 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
737 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000738 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800739 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000740 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000741 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800742 << "Should reject motion events with 0 pointers.";
743
Garfield Tanfbe732e2020-01-24 11:26:14 -0800744 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
745 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700746 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700747 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
748 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with more than MAX_POINTERS pointers.";
754
755 // Rejects motion events with invalid pointer ids.
756 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800757 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
758 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700759 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700760 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
761 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000762 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800763 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000764 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000765 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800766 << "Should reject motion events with pointer ids less than 0.";
767
768 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800769 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
770 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700771 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
773 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000774 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800775 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000776 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000777 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800778 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
779
780 // Rejects motion events with duplicate pointer ids.
781 pointerProperties[0].id = 1;
782 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800783 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
784 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700785 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700786 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
787 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000788 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800789 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000790 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000791 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800792 << "Should reject motion events with duplicate pointer ids.";
793}
794
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800795/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
796
797TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
798 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000799 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800800 ASSERT_TRUE(mDispatcher->waitForIdle());
801
802 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
803}
804
805TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000806 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
807 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000808 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800809
810 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
811 args.policyFlags |= POLICY_FLAG_TRUSTED;
812 mFakePolicy->assertNotifySwitchWasCalled(args);
813}
814
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700815namespace {
816
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700817static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700818// Default input dispatching timeout if there is no focused application or paused window
819// from which to determine an appropriate dispatching timeout.
820static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
821 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
822 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800823
824class FakeApplicationHandle : public InputApplicationHandle {
825public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700826 FakeApplicationHandle() {
827 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700828 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500829 mInfo.dispatchingTimeoutMillis =
830 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700831 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800832 virtual ~FakeApplicationHandle() {}
833
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000834 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700835
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500836 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
837 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700838 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800839};
840
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800841class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800842public:
Garfield Tan15601662020-09-22 15:32:38 -0700843 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800844 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700845 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800846 }
847
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700848 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700849 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700850 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700851 if (!consumeSeq) {
852 return nullptr;
853 }
854 finishEvent(*consumeSeq);
855 return event;
856 }
857
858 /**
859 * Receive an event without acknowledging it.
860 * Return the sequence number that could later be used to send finished signal.
861 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700862 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
863 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800864 uint32_t consumeSeq;
865 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800866
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800867 std::chrono::time_point start = std::chrono::steady_clock::now();
868 status_t status = WOULD_BLOCK;
869 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000870 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800871 &event);
872 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700873 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800874 break;
875 }
876 }
877
878 if (status == WOULD_BLOCK) {
879 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800881 }
882
883 if (status != OK) {
884 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 }
887 if (event == nullptr) {
888 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700889 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700891 if (outEvent != nullptr) {
892 *outEvent = event;
893 }
894 return consumeSeq;
895 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 /**
898 * To be used together with "receiveEvent" to complete the consumption of an event.
899 */
900 void finishEvent(uint32_t consumeSeq) {
901 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
902 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800903 }
904
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000905 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
906 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
907 ASSERT_EQ(OK, status);
908 }
909
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700910 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000911 std::optional<int32_t> expectedDisplayId,
912 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700913 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800914
915 ASSERT_NE(nullptr, event) << mName.c_str()
916 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700918 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
919 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800920
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000921 if (expectedDisplayId.has_value()) {
922 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
923 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800924
Tiger Huang8664f8c2018-10-11 19:14:35 +0800925 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700926 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800927 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700928 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000929 if (expectedFlags.has_value()) {
930 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
931 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800932 break;
933 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700934 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800935 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700936 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000937 if (expectedFlags.has_value()) {
938 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
939 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800940 break;
941 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100943 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
944 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700945 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800946 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
947 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700948 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000949 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
950 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700951 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800952 FAIL() << "Use 'consumeDragEvent' for DRAG events";
953 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800954 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800955 }
956
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800957 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700958 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800959
960 if (event == nullptr) {
961 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
962 return nullptr;
963 }
964
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 if (event->getType() != InputEventType::MOTION) {
966 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800967 return nullptr;
968 }
969 return static_cast<MotionEvent*>(event);
970 }
971
972 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
973 MotionEvent* motionEvent = consumeMotion();
974 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
975 ASSERT_THAT(*motionEvent, matcher);
976 }
977
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100978 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700979 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100980 ASSERT_NE(nullptr, event) << mName.c_str()
981 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700982 ASSERT_EQ(InputEventType::FOCUS, event->getType())
983 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100984
985 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
986 << mName.c_str() << ": event displayId should always be NONE.";
987
988 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
989 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 }
991
Prabir Pradhan99987712020-11-10 18:43:05 -0800992 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700993 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -0800994 ASSERT_NE(nullptr, event) << mName.c_str()
995 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
997 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -0800998
999 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1000 << mName.c_str() << ": event displayId should always be NONE.";
1001
1002 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1003 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1004 }
1005
arthurhungb89ccb02020-12-30 16:19:01 +08001006 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001007 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001008 ASSERT_NE(nullptr, event) << mName.c_str()
1009 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001011
1012 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1013 << mName.c_str() << ": event displayId should always be NONE.";
1014
1015 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1016 EXPECT_EQ(isExiting, dragEvent.isExiting());
1017 EXPECT_EQ(x, dragEvent.getX());
1018 EXPECT_EQ(y, dragEvent.getY());
1019 }
1020
Antonio Kantekf16f2832021-09-28 04:39:20 +00001021 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001022 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001023 ASSERT_NE(nullptr, event) << mName.c_str()
1024 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001025 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1026 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001027
1028 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1029 << mName.c_str() << ": event displayId should always be NONE.";
1030 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1031 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1032 }
1033
chaviwd1c23182019-12-20 18:44:56 -08001034 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001035 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001036 if (event == nullptr) {
1037 return;
1038 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001039 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001040 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1041 ADD_FAILURE() << "Received key event "
1042 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001044 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1045 ADD_FAILURE() << "Received motion event "
1046 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001047 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001048 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1049 ADD_FAILURE() << "Received focus event, hasFocus = "
1050 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001051 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001052 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1053 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1054 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001056 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1057 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1058 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 }
1060 FAIL() << mName.c_str()
1061 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001062 }
1063
1064 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1065
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001066 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1067
chaviwd1c23182019-12-20 18:44:56 -08001068protected:
1069 std::unique_ptr<InputConsumer> mConsumer;
1070 PreallocatedInputEventFactory mEventFactory;
1071
1072 std::string mName;
1073};
1074
chaviw3277faf2021-05-19 16:45:23 -05001075class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001076public:
1077 static const int32_t WIDTH = 600;
1078 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001079
Chris Yea209fde2020-07-22 13:54:51 -07001080 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001081 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001082 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001083 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001084 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001085 base::Result<std::unique_ptr<InputChannel>> channel =
1086 dispatcher->createInputChannel(name);
1087 token = (*channel)->getConnectionToken();
1088 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001089 }
1090
1091 inputApplicationHandle->updateInfo();
1092 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1093
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001094 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001095 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001096 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001097 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001098 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001099 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001100 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001101 mInfo.globalScaleFactor = 1.0;
1102 mInfo.touchableRegion.clear();
1103 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001104 mInfo.ownerPid = WINDOW_PID;
1105 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001106 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001107 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001108 }
1109
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001110 sp<FakeWindowHandle> clone(int32_t displayId) {
1111 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1112 handle->mInfo = mInfo;
1113 handle->mInfo.displayId = displayId;
1114 handle->mInfo.id = sId++;
1115 handle->mInputReceiver = mInputReceiver;
1116 return handle;
1117 }
1118
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001119 void setTouchable(bool touchable) {
1120 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1121 }
chaviwd1c23182019-12-20 18:44:56 -08001122
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001123 void setFocusable(bool focusable) {
1124 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1125 }
1126
1127 void setVisible(bool visible) {
1128 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1129 }
Vishnu Nair958da932020-08-21 17:12:37 -07001130
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001131 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001132 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001133 }
1134
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001135 void setPaused(bool paused) {
1136 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1137 }
1138
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001139 void setPreventSplitting(bool preventSplitting) {
1140 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001141 }
1142
1143 void setSlippery(bool slippery) {
1144 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1145 }
1146
1147 void setWatchOutsideTouch(bool watchOutside) {
1148 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1149 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001150
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001151 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1152
1153 void setInterceptsStylus(bool interceptsStylus) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1155 }
1156
1157 void setDropInput(bool dropInput) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1159 }
1160
1161 void setDropInputIfObscured(bool dropInputIfObscured) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1163 }
1164
1165 void setNoInputChannel(bool noInputChannel) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1167 }
1168
Josep del Riob3981622023-04-18 15:49:45 +00001169 void setDisableUserActivity(bool disableUserActivity) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1171 }
1172
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001173 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1174
chaviw3277faf2021-05-19 16:45:23 -05001175 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001176
Bernardo Rufino7393d172021-02-26 13:56:11 +00001177 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1178
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001179 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001180 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001181 mInfo.touchableRegion.clear();
1182 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001183
1184 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1185 ui::Transform translate;
1186 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1187 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001188 }
1189
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001190 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1191
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001192 void setIsWallpaper(bool isWallpaper) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1194 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001195
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001196 void setDupTouchToWallpaper(bool hasWallpaper) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1198 }
chaviwd1c23182019-12-20 18:44:56 -08001199
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001200 void setTrustedOverlay(bool trustedOverlay) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1202 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001203
chaviw9eaa22c2020-07-01 16:21:27 -07001204 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1205 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1206 }
1207
1208 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001209
yunho.shinf4a80b82020-11-16 21:13:57 +09001210 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1211
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001212 KeyEvent* consumeKey() {
1213 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1214 if (event == nullptr) {
1215 ADD_FAILURE() << "Consume failed : no event";
1216 return nullptr;
1217 }
1218 if (event->getType() != InputEventType::KEY) {
1219 ADD_FAILURE() << "Instead of key event, got " << *event;
1220 return nullptr;
1221 }
1222 return static_cast<KeyEvent*>(event);
1223 }
1224
1225 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1226 KeyEvent* keyEvent = consumeKey();
1227 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1228 ASSERT_THAT(*keyEvent, matcher);
1229 }
1230
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001231 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001232 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001233 }
1234
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001235 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001236 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001237 }
1238
Svet Ganov5d3bc372020-01-26 23:11:07 -08001239 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001240 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001241 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1242 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001243 }
1244
1245 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001246 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001247 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1248 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001249 }
1250
1251 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001252 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001253 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1254 }
1255
1256 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1257 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001258 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001259 expectedFlags);
1260 }
1261
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001263 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1264 int32_t expectedFlags = 0) {
1265 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
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 consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001271 int32_t expectedFlags = 0) {
1272 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1273 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001274 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001275 }
1276
1277 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001278 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001280 expectedFlags);
1281 }
1282
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001283 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1284 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001285 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001286 expectedFlags);
1287 }
1288
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001289 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1290 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001291 MotionEvent* motionEvent = consumeMotion();
1292 ASSERT_NE(nullptr, motionEvent);
1293 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1294 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1295 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001296 }
1297
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001298 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1299 ASSERT_NE(mInputReceiver, nullptr)
1300 << "Cannot consume events from a window with no receiver";
1301 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1302 }
1303
Prabir Pradhan99987712020-11-10 18:43:05 -08001304 void consumeCaptureEvent(bool hasCapture) {
1305 ASSERT_NE(mInputReceiver, nullptr)
1306 << "Cannot consume events from a window with no receiver";
1307 mInputReceiver->consumeCaptureEvent(hasCapture);
1308 }
1309
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001310 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1311 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001312 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001313 ASSERT_THAT(*motionEvent, matcher);
1314 }
1315
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001316 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001317 std::optional<int32_t> expectedDisplayId,
1318 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001319 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1320 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1321 expectedFlags);
1322 }
1323
arthurhungb89ccb02020-12-30 16:19:01 +08001324 void consumeDragEvent(bool isExiting, float x, float y) {
1325 mInputReceiver->consumeDragEvent(isExiting, x, y);
1326 }
1327
Antonio Kantekf16f2832021-09-28 04:39:20 +00001328 void consumeTouchModeEvent(bool inTouchMode) {
1329 ASSERT_NE(mInputReceiver, nullptr)
1330 << "Cannot consume events from a window with no receiver";
1331 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1332 }
1333
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001334 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001335 if (mInputReceiver == nullptr) {
1336 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1337 return std::nullopt;
1338 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001339 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001340 }
1341
1342 void finishEvent(uint32_t sequenceNum) {
1343 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1344 mInputReceiver->finishEvent(sequenceNum);
1345 }
1346
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001347 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1348 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1349 mInputReceiver->sendTimeline(inputEventId, timeline);
1350 }
1351
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001352 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001353 if (mInputReceiver == nullptr) {
1354 return nullptr;
1355 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001356 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001357 }
1358
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001359 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001360 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001361 if (event == nullptr) {
1362 ADD_FAILURE() << "Consume failed : no event";
1363 return nullptr;
1364 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001365 if (event->getType() != InputEventType::MOTION) {
1366 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001367 return nullptr;
1368 }
1369 return static_cast<MotionEvent*>(event);
1370 }
1371
Arthur Hungb92218b2018-08-14 12:00:21 +08001372 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001373 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001374 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001375 return; // Can't receive events if the window does not have input channel
1376 }
1377 ASSERT_NE(nullptr, mInputReceiver)
1378 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001379 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001380 }
1381
chaviwaf87b3e2019-10-01 16:59:28 -07001382 sp<IBinder> getToken() { return mInfo.token; }
1383
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001384 const std::string& getName() { return mName; }
1385
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001386 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001387 mInfo.ownerPid = ownerPid;
1388 mInfo.ownerUid = ownerUid;
1389 }
1390
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001391 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001392
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001393 void destroyReceiver() { mInputReceiver = nullptr; }
1394
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001395 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1396
chaviwd1c23182019-12-20 18:44:56 -08001397private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001398 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001399 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001400 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001401 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001402 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001403};
1404
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001405std::atomic<int32_t> FakeWindowHandle::sId{1};
1406
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001407class FakeMonitorReceiver {
1408public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001409 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001410 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001411 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001412 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1413 }
1414
1415 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1416
1417 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1418 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1419 expectedFlags);
1420 }
1421
1422 std::optional<int32_t> receiveEvent() {
1423 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1424 }
1425
1426 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1427
1428 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1429 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1430 expectedDisplayId, expectedFlags);
1431 }
1432
1433 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1434 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1435 expectedDisplayId, expectedFlags);
1436 }
1437
1438 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1439 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1440 expectedDisplayId, expectedFlags);
1441 }
1442
1443 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1444 mInputReceiver->consumeMotionEvent(
1445 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1446 WithDisplayId(expectedDisplayId),
1447 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1448 }
1449
1450 void consumeMotionPointerDown(int32_t pointerIdx) {
1451 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1452 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1453 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1454 /*expectedFlags=*/0);
1455 }
1456
1457 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1458 mInputReceiver->consumeMotionEvent(matcher);
1459 }
1460
1461 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1462
1463 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1464
1465private:
1466 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1467};
1468
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001469static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001470 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471 int32_t displayId = ADISPLAY_ID_NONE,
1472 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001473 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001474 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001475 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001476 KeyEvent event;
1477 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1478
1479 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001480 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001481 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1482 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001483
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001484 if (!allowKeyRepeat) {
1485 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1486 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001487 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001488 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001489}
1490
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001491static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1492 InputEventInjectionResult result =
1493 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1494 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1495 if (result != InputEventInjectionResult::TIMED_OUT) {
1496 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1497 }
1498}
1499
1500static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001502 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001503}
1504
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001505// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1506// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1507// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001508static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1509 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001510 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001511 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001512 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001513}
1514
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001515static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001516 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001517 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001518}
1519
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001520static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001521 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001522 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001523 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001524 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001525 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1526 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001527}
1528
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001529static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001530 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1531 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001532 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001533 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1534 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001535 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001536 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001537 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001538 MotionEventBuilder motionBuilder =
1539 MotionEventBuilder(action, source)
1540 .displayId(displayId)
1541 .eventTime(eventTime)
1542 .rawXCursorPosition(cursorPosition.x)
1543 .rawYCursorPosition(cursorPosition.y)
1544 .pointer(
1545 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1546 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1547 motionBuilder.downTime(eventTime);
1548 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001549
1550 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001551 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1552 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001553}
1554
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001555static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1556 int32_t displayId,
1557 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001558 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001559}
1560
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001561static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1562 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001563 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001564 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001565}
1566
Jackal Guof9696682018-10-05 12:23:23 +08001567static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1568 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1569 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001570 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001571 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1572 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001573
1574 return args;
1575}
1576
Josep del Riob3981622023-04-18 15:49:45 +00001577static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1578 int32_t displayId = ADISPLAY_ID_NONE) {
1579 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1580 // Define a valid key event.
1581 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001582 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001583 currentTime);
1584
1585 return args;
1586}
1587
1588static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1589 int32_t displayId = ADISPLAY_ID_NONE) {
1590 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1591 // Define a valid key event.
1592 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001593 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001594 AMETA_NONE, currentTime);
1595
1596 return args;
1597}
1598
Prabir Pradhan678438e2023-04-13 19:32:51 +00001599[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1600 int32_t displayId,
1601 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001602 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001603 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1604 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1605 }
1606
chaviwd1c23182019-12-20 18:44:56 -08001607 PointerProperties pointerProperties[pointerCount];
1608 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001609
chaviwd1c23182019-12-20 18:44:56 -08001610 for (size_t i = 0; i < pointerCount; i++) {
1611 pointerProperties[i].clear();
1612 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001613 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001614
chaviwd1c23182019-12-20 18:44:56 -08001615 pointerCoords[i].clear();
1616 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1617 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1618 }
Jackal Guof9696682018-10-05 12:23:23 +08001619
1620 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1621 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001622 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001623 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1624 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001625 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001626 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001627 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001628 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001629
1630 return args;
1631}
1632
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001633static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1634 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1635}
1636
chaviwd1c23182019-12-20 18:44:56 -08001637static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1638 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1639}
1640
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001641static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1642 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001643 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001644}
1645
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001646} // namespace
1647
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001648/**
1649 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1650 * broken channel.
1651 */
1652TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1654 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001655 sp<FakeWindowHandle>::make(application, mDispatcher,
1656 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001657
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001659
1660 // Window closes its channel, but the window remains.
1661 window->destroyReceiver();
1662 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1663}
1664
Arthur Hungb92218b2018-08-14 12:00:21 +08001665TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001667 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1668 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001669
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001672 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001674
1675 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001676 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001677}
1678
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001679TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1682 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001685 // Inject a MotionEvent to an unknown display.
1686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001687 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1689
1690 // Window should receive motion event.
1691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1692}
1693
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001694/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001695 * Calling onWindowInfosChanged once should not cause any issues.
1696 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697 * called twice.
1698 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001699TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001701 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1702 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001707 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710
1711 // Window should receive motion event.
1712 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1713}
1714
1715/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001716 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717 */
1718TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001720 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1721 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001722 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001724 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001728 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001730
1731 // Window should receive motion event.
1732 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1733}
1734
Arthur Hungb92218b2018-08-14 12:00:21 +08001735// The foreground window should receive the first touch down event.
1736TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001738 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001739 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001740 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001741 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001742
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001743 mDispatcher->onWindowInfosChanged(
1744 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001748
1749 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001750 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001751 windowSecond->assertNoEvents();
1752}
1753
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001754/**
1755 * Two windows: A top window, and a wallpaper behind the window.
1756 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1757 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001758 * 1. foregroundWindow <-- dup touch to wallpaper
1759 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001760 */
1761TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1763 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001764 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001765 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001766 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001767 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001768 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001769
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001770 mDispatcher->onWindowInfosChanged(
1771 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001773 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001774 {100, 200}))
1775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1776
1777 // Both foreground window and its wallpaper should receive the touch down
1778 foregroundWindow->consumeMotionDown();
1779 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1780
1781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001782 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001783 ADISPLAY_ID_DEFAULT, {110, 200}))
1784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1785
1786 foregroundWindow->consumeMotionMove();
1787 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1788
1789 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001790 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001791 foregroundWindow->consumeMotionCancel();
1792 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1793 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1794}
1795
1796/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001797 * Two fingers down on the window, and lift off the first finger.
1798 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1799 * contains a single pointer.
1800 */
1801TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1802 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1803 sp<FakeWindowHandle> window =
1804 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1805
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001806 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001807 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1809 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1810 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001811 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001812 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1813 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1814 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1815 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001816 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001817 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1818 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1819 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1820 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001821 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1822 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1823 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1824
1825 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001826 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001827 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1828 window->consumeMotionEvent(
1829 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1830}
1831
1832/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001833 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1834 * with the following differences:
1835 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1836 * clean up the connection.
1837 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1838 * Ensure that there's no crash in the dispatcher.
1839 */
1840TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1842 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001843 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001844 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001845 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001846 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001847 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001848
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001849 mDispatcher->onWindowInfosChanged(
1850 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 {100, 200}))
1854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1855
1856 // Both foreground window and its wallpaper should receive the touch down
1857 foregroundWindow->consumeMotionDown();
1858 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1859
1860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001861 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862 ADISPLAY_ID_DEFAULT, {110, 200}))
1863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1864
1865 foregroundWindow->consumeMotionMove();
1866 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1867
1868 // Wallpaper closes its channel, but the window remains.
1869 wallpaperWindow->destroyReceiver();
1870 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1871
1872 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1873 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001874 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001875 foregroundWindow->consumeMotionCancel();
1876}
1877
Arthur Hungc539dbb2022-12-08 07:45:36 +00001878class ShouldSplitTouchFixture : public InputDispatcherTest,
1879 public ::testing::WithParamInterface<bool> {};
1880INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1881 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001882/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883 * A single window that receives touch (on top), and a wallpaper window underneath it.
1884 * The top window gets a multitouch gesture.
1885 * Ensure that wallpaper gets the same gesture.
1886 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001889 sp<FakeWindowHandle> foregroundWindow =
1890 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1891 foregroundWindow->setDupTouchToWallpaper(true);
1892 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893
1894 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001895 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001896 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001898 mDispatcher->onWindowInfosChanged(
1899 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900
1901 // Touch down on top window
1902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001903 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 {100, 100}))
1905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1906
1907 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001908 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1910
1911 // Second finger down on the top window
1912 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001913 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001914 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001915 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1916 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917 .build();
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001919 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001920 InputEventInjectionSync::WAIT_FOR_RESULT))
1921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1922
Harry Cutts33476232023-01-30 19:57:29 +00001923 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1924 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001926
1927 const MotionEvent secondFingerUpEvent =
1928 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1929 .displayId(ADISPLAY_ID_DEFAULT)
1930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001933 .build();
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001936 InputEventInjectionSync::WAIT_FOR_RESULT))
1937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1938 foregroundWindow->consumeMotionPointerUp(0);
1939 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1940
1941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001942 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001943 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1944 AINPUT_SOURCE_TOUCHSCREEN)
1945 .displayId(ADISPLAY_ID_DEFAULT)
1946 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001947 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001948 .x(100)
1949 .y(100))
1950 .build(),
1951 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001952 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1953 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1954 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955}
1956
1957/**
1958 * Two windows: a window on the left and window on the right.
1959 * A third window, wallpaper, is behind both windows, and spans both top windows.
1960 * The first touch down goes to the left window. A second pointer touches down on the right window.
1961 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1962 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1963 * ACTION_POINTER_DOWN(1).
1964 */
1965TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1966 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1967 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001968 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001970 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001971
1972 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001973 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001975 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976
1977 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001978 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001980 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001981
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001982 mDispatcher->onWindowInfosChanged(
1983 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1984 {},
1985 0,
1986 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987
1988 // Touch down on left window
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001990 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991 {100, 100}))
1992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1993
1994 // Both foreground window and its wallpaper should receive the touch down
1995 leftWindow->consumeMotionDown();
1996 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1997
1998 // Second finger down on the right window
1999 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002000 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002001 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002002 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2003 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 .build();
2005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002006 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007 InputEventInjectionSync::WAIT_FOR_RESULT))
2008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2009
2010 leftWindow->consumeMotionMove();
2011 // Since the touch is split, right window gets ACTION_DOWN
2012 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002013 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014 expectedWallpaperFlags);
2015
2016 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002017 mDispatcher->onWindowInfosChanged(
2018 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002019 leftWindow->consumeMotionCancel();
2020 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2021 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2022
2023 // The pointer that's still down on the right window moves, and goes to the right window only.
2024 // As far as the dispatcher's concerned though, both pointers are still present.
2025 const MotionEvent secondFingerMoveEvent =
2026 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2027 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002028 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2029 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 .build();
2031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002032 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 InputEventInjectionSync::WAIT_FOR_RESULT));
2034 rightWindow->consumeMotionMove();
2035
2036 leftWindow->assertNoEvents();
2037 rightWindow->assertNoEvents();
2038 wallpaperWindow->assertNoEvents();
2039}
2040
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041/**
2042 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2043 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2044 * The right window should receive ACTION_DOWN.
2045 */
2046TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048 sp<FakeWindowHandle> leftWindow =
2049 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2050 leftWindow->setFrame(Rect(0, 0, 200, 200));
2051 leftWindow->setDupTouchToWallpaper(true);
2052 leftWindow->setSlippery(true);
2053
2054 sp<FakeWindowHandle> rightWindow =
2055 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2056 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002057
2058 sp<FakeWindowHandle> wallpaperWindow =
2059 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2060 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002061
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002062 mDispatcher->onWindowInfosChanged(
2063 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2064 {},
2065 0,
2066 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002067
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002070 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002071 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002073
2074 // Both foreground window and its wallpaper should receive the touch down
2075 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002076 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2077
Arthur Hungc539dbb2022-12-08 07:45:36 +00002078 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002080 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2083
Arthur Hungc539dbb2022-12-08 07:45:36 +00002084 leftWindow->consumeMotionCancel();
2085 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2086 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002087}
2088
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002089/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002090 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2091 * interactive, it might stop sending this flag.
2092 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2093 * to have a consistent input stream.
2094 *
2095 * Test procedure:
2096 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2097 * DOWN (new gesture).
2098 *
2099 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2100 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2101 *
2102 * We technically just need a single window here, but we are using two windows (spy on top and a
2103 * regular window below) to emulate the actual situation where it happens on the device.
2104 */
2105TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2107 sp<FakeWindowHandle> spyWindow =
2108 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2109 spyWindow->setFrame(Rect(0, 0, 200, 200));
2110 spyWindow->setTrustedOverlay(true);
2111 spyWindow->setSpy(true);
2112
2113 sp<FakeWindowHandle> window =
2114 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2115 window->setFrame(Rect(0, 0, 200, 200));
2116
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002117 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002118 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002119
2120 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002121 mDispatcher->notifyMotion(
2122 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2123 .deviceId(touchDeviceId)
2124 .policyFlags(DEFAULT_POLICY_FLAGS)
2125 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2126 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127
Prabir Pradhan678438e2023-04-13 19:32:51 +00002128 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2129 .deviceId(touchDeviceId)
2130 .policyFlags(DEFAULT_POLICY_FLAGS)
2131 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2132 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2133 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2135 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2136 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2137 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2138
2139 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002140 mDispatcher->notifyMotion(
2141 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2142 .deviceId(touchDeviceId)
2143 .policyFlags(0)
2144 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2145 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2146 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002147 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2148 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2149
2150 // We don't need to reset the device to reproduce the issue, but the reset event typically
2151 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002152 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002153
2154 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002155 mDispatcher->notifyMotion(
2156 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2157 .deviceId(touchDeviceId)
2158 .policyFlags(DEFAULT_POLICY_FLAGS)
2159 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2160 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002161 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2162 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2163
2164 // No more events
2165 spyWindow->assertNoEvents();
2166 window->assertNoEvents();
2167}
2168
2169/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002170 * Two windows: a window on the left and a window on the right.
2171 * Mouse is hovered from the right window into the left window.
2172 * Next, we tap on the left window, where the cursor was last seen.
2173 * The second tap is done onto the right window.
2174 * The mouse and tap are from two different devices.
2175 * We technically don't need to set the downtime / eventtime for these events, but setting these
2176 * explicitly helps during debugging.
2177 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2178 * In the buggy implementation, a tap on the right window would cause a crash.
2179 */
2180TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2182 sp<FakeWindowHandle> leftWindow =
2183 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2184 leftWindow->setFrame(Rect(0, 0, 200, 200));
2185
2186 sp<FakeWindowHandle> rightWindow =
2187 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2188 rightWindow->setFrame(Rect(200, 0, 400, 200));
2189
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002190 mDispatcher->onWindowInfosChanged(
2191 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002192 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2193 // stale.
2194 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2195 const int32_t mouseDeviceId = 6;
2196 const int32_t touchDeviceId = 4;
2197 // Move the cursor from right
2198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002199 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002200 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2201 AINPUT_SOURCE_MOUSE)
2202 .deviceId(mouseDeviceId)
2203 .downTime(baseTime + 10)
2204 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002205 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002206 .build()));
2207 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2208
2209 // .. to the left window
2210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002211 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002212 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2213 AINPUT_SOURCE_MOUSE)
2214 .deviceId(mouseDeviceId)
2215 .downTime(baseTime + 10)
2216 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002217 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002218 .build()));
2219 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2220 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2221 // Now tap the left window
2222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002223 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002224 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2225 AINPUT_SOURCE_TOUCHSCREEN)
2226 .deviceId(touchDeviceId)
2227 .downTime(baseTime + 40)
2228 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002229 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002230 .build()));
2231 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2232 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2233
2234 // release tap
2235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002236 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002237 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2238 AINPUT_SOURCE_TOUCHSCREEN)
2239 .deviceId(touchDeviceId)
2240 .downTime(baseTime + 40)
2241 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002242 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002243 .build()));
2244 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2245
2246 // Tap the window on the right
2247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002248 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002249 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2250 AINPUT_SOURCE_TOUCHSCREEN)
2251 .deviceId(touchDeviceId)
2252 .downTime(baseTime + 60)
2253 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002254 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002255 .build()));
2256 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2257
2258 // release tap
2259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002260 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002261 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2262 AINPUT_SOURCE_TOUCHSCREEN)
2263 .deviceId(touchDeviceId)
2264 .downTime(baseTime + 60)
2265 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002266 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002267 .build()));
2268 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2269
2270 // No more events
2271 leftWindow->assertNoEvents();
2272 rightWindow->assertNoEvents();
2273}
2274
2275/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002276 * Start hovering in a window. While this hover is still active, make another window appear on top.
2277 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2278 * While the top window is present, the hovering is stopped.
2279 * Later, hovering gets resumed again.
2280 * Ensure that new hover gesture is handled correctly.
2281 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2282 * to the window that's currently being hovered over.
2283 */
2284TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2286 sp<FakeWindowHandle> window =
2287 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2288 window->setFrame(Rect(0, 0, 200, 200));
2289
2290 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002292
2293 // Start hovering in the window
2294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2295 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2296 .build());
2297 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2298
2299 // Now, an obscuring window appears!
2300 sp<FakeWindowHandle> obscuringWindow =
2301 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2302 ADISPLAY_ID_DEFAULT,
2303 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2304 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2305 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2306 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2307 obscuringWindow->setNoInputChannel(true);
2308 obscuringWindow->setFocusable(false);
2309 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002310 mDispatcher->onWindowInfosChanged(
2311 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002312
2313 // While this new obscuring window is present, the hovering is stopped
2314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2315 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2316 .build());
2317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2318
2319 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002320 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002321
2322 // And a new hover gesture starts.
2323 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2324 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2325 .build());
2326 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2327}
2328
2329/**
2330 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2331 * the obscuring window.
2332 */
2333TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2334 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2335 sp<FakeWindowHandle> window =
2336 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2337 window->setFrame(Rect(0, 0, 200, 200));
2338
2339 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002340 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002341
2342 // Start hovering in the window
2343 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2344 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2345 .build());
2346 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2347
2348 // Now, an obscuring window appears!
2349 sp<FakeWindowHandle> obscuringWindow =
2350 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2351 ADISPLAY_ID_DEFAULT,
2352 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2353 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2354 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2355 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2356 obscuringWindow->setNoInputChannel(true);
2357 obscuringWindow->setFocusable(false);
2358 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002359 mDispatcher->onWindowInfosChanged(
2360 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002361
2362 // While this new obscuring window is present, the hovering continues. The event can't go to the
2363 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2365 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2366 .build());
2367 obscuringWindow->assertNoEvents();
2368 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2369
2370 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002371 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002372
2373 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2374 // so it should generate a HOVER_ENTER
2375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2376 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2377 .build());
2378 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2379
2380 // Now the MOVE should be getting dispatched normally
2381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2382 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2383 .build());
2384 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2385}
2386
2387/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002388 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2389 * events are delivered to the window.
2390 */
2391TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2392 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2393 sp<FakeWindowHandle> window =
2394 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2395 window->setFrame(Rect(0, 0, 200, 200));
2396 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2397
2398 // Start hovering in the window
2399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2400 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2401 .build());
2402 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2403
2404 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2405 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2406 .build());
2407 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2408
2409 // Scroll with the mouse
2410 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2411 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2412 .build());
2413 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2414}
2415
2416using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2417
2418/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002419 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2420 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002421 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002422TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2424 sp<FakeWindowHandle> window =
2425 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2426 window->setFrame(Rect(0, 0, 200, 200));
2427
2428 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2429
2430 constexpr int32_t touchDeviceId = 4;
2431 constexpr int32_t stylusDeviceId = 2;
2432
2433 // Stylus down
2434 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2435 .deviceId(stylusDeviceId)
2436 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2437 .build());
2438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2439
2440 // Touch down
2441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2442 .deviceId(touchDeviceId)
2443 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2444 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002445
2446 // Touch move
2447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2448 .deviceId(touchDeviceId)
2449 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2450 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002451 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002452
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002453 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002454 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2455 .deviceId(stylusDeviceId)
2456 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2457 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002458 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2459 WithCoords(101, 111)));
2460
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002461 window->assertNoEvents();
2462}
2463
2464/**
2465 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002466 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002467 * Similar test as above, but with added SPY window.
2468 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002469TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2471 sp<FakeWindowHandle> window =
2472 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2473 sp<FakeWindowHandle> spyWindow =
2474 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2475 spyWindow->setFrame(Rect(0, 0, 200, 200));
2476 spyWindow->setTrustedOverlay(true);
2477 spyWindow->setSpy(true);
2478 window->setFrame(Rect(0, 0, 200, 200));
2479
2480 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2481
2482 constexpr int32_t touchDeviceId = 4;
2483 constexpr int32_t stylusDeviceId = 2;
2484
2485 // Stylus down
2486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2487 .deviceId(stylusDeviceId)
2488 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2489 .build());
2490 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2491 spyWindow->consumeMotionEvent(
2492 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2493
2494 // Touch down
2495 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2496 .deviceId(touchDeviceId)
2497 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2498 .build());
2499
2500 // Touch move
2501 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2502 .deviceId(touchDeviceId)
2503 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2504 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002505
2506 // Touch is ignored because stylus is already down
2507
2508 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2510 .deviceId(stylusDeviceId)
2511 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2512 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002513 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2514 WithCoords(101, 111)));
2515 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2516 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002517
2518 window->assertNoEvents();
2519 spyWindow->assertNoEvents();
2520}
2521
2522/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002523 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2524 * touch is not dropped, because stylus hover should be ignored.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002525 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002526TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2528 sp<FakeWindowHandle> window =
2529 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2530 window->setFrame(Rect(0, 0, 200, 200));
2531
2532 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2533
2534 constexpr int32_t touchDeviceId = 4;
2535 constexpr int32_t stylusDeviceId = 2;
2536
2537 // Stylus down on the window
2538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2539 .deviceId(stylusDeviceId)
2540 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2541 .build());
2542 window->consumeMotionEvent(
2543 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2544
2545 // Touch down on window
2546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2547 .deviceId(touchDeviceId)
2548 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2549 .build());
2550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2551 .deviceId(touchDeviceId)
2552 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2553 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002554
2555 // Stylus hover is canceled because touch is down
2556 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT),
2557 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2558 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2559 WithCoords(140, 145)));
2560 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2561 WithCoords(141, 146)));
2562
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002563 // Subsequent stylus movements are ignored
2564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2565 .deviceId(stylusDeviceId)
2566 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2567 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002568
2569 // but subsequent touches continue to be delivered
2570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2571 .deviceId(touchDeviceId)
2572 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2573 .build());
2574 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2575 WithCoords(142, 147)));
2576}
2577
2578/**
2579 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2580 * Ensure that touch is not canceled, because stylus hover should be dropped.
2581 */
2582TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2584 sp<FakeWindowHandle> window =
2585 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2586 window->setFrame(Rect(0, 0, 200, 200));
2587
2588 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2589
2590 constexpr int32_t touchDeviceId = 4;
2591 constexpr int32_t stylusDeviceId = 2;
2592
2593 // Touch down on window
2594 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2595 .deviceId(touchDeviceId)
2596 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2597 .build());
2598 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2599 .deviceId(touchDeviceId)
2600 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2601 .build());
2602 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2603 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2604
2605 // Stylus hover on the window
2606 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2607 .deviceId(stylusDeviceId)
2608 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2609 .build());
2610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2611 .deviceId(stylusDeviceId)
2612 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2613 .build());
2614 // Stylus hover movement is dropped
2615
2616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2617 .deviceId(touchDeviceId)
2618 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2619 .build());
2620 // Subsequent touch movements are delivered correctly
2621 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2622 WithCoords(142, 147)));
2623}
2624
2625/**
2626 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2627 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2628 * become active.
2629 */
2630TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2632 sp<FakeWindowHandle> window =
2633 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2634 window->setFrame(Rect(0, 0, 200, 200));
2635
2636 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2637
2638 constexpr int32_t stylusDeviceId1 = 3;
2639 constexpr int32_t stylusDeviceId2 = 5;
2640
2641 // Touch down on window
2642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2643 .deviceId(stylusDeviceId1)
2644 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2645 .build());
2646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2647 .deviceId(stylusDeviceId1)
2648 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2649 .build());
2650 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2651 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2652
2653 // Second stylus down
2654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2655 .deviceId(stylusDeviceId2)
2656 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2657 .build());
2658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2659 .deviceId(stylusDeviceId2)
2660 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2661 .build());
2662
2663 // First stylus is canceled, second one takes over.
2664 window->consumeMotionEvent(
2665 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2666 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2667 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2668
2669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2670 .deviceId(stylusDeviceId1)
2671 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2672 .build());
2673 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002674 window->assertNoEvents();
2675}
2676
2677/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002678 * One window. Touch down on the window. Then, stylus down on the window from another device.
2679 * Ensure that is canceled, because stylus down should be preferred over touch.
2680 */
2681TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2683 sp<FakeWindowHandle> window =
2684 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2685 window->setFrame(Rect(0, 0, 200, 200));
2686
2687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2688
2689 constexpr int32_t touchDeviceId = 4;
2690 constexpr int32_t stylusDeviceId = 2;
2691
2692 // Touch down on window
2693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
2695 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2696 .build());
2697 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2698 .deviceId(touchDeviceId)
2699 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2700 .build());
2701 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2702 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2703
2704 // Stylus down on the window
2705 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2706 .deviceId(stylusDeviceId)
2707 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2708 .build());
2709 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2710 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2711
2712 // Subsequent stylus movements are delivered correctly
2713 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2714 .deviceId(stylusDeviceId)
2715 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2716 .build());
2717 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2718 WithCoords(101, 111)));
2719}
2720
2721/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002722 * Two windows: a window on the left and a window on the right.
2723 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2724 * down. Then, on the left window, also place second touch pointer down.
2725 * This test tries to reproduce a crash.
2726 * In the buggy implementation, second pointer down on the left window would cause a crash.
2727 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002728TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2730 sp<FakeWindowHandle> leftWindow =
2731 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2732 leftWindow->setFrame(Rect(0, 0, 200, 200));
2733
2734 sp<FakeWindowHandle> rightWindow =
2735 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2736 rightWindow->setFrame(Rect(200, 0, 400, 200));
2737
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002738 mDispatcher->onWindowInfosChanged(
2739 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002740
2741 const int32_t touchDeviceId = 4;
2742 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002743
2744 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2746 .deviceId(mouseDeviceId)
2747 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2748 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002749 leftWindow->consumeMotionEvent(
2750 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2751
2752 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002753 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2754 .deviceId(mouseDeviceId)
2755 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2756 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2757 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002758
2759 leftWindow->consumeMotionEvent(
2760 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2761 leftWindow->consumeMotionEvent(
2762 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2763
Prabir Pradhan678438e2023-04-13 19:32:51 +00002764 mDispatcher->notifyMotion(
2765 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2766 .deviceId(mouseDeviceId)
2767 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2768 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2769 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2770 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002771 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2772
2773 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2775 .deviceId(touchDeviceId)
2776 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2777 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002778 leftWindow->assertNoEvents();
2779
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002780 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2781
2782 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002783 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2784 .deviceId(touchDeviceId)
2785 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2786 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2787 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002788 // Since this is now a new splittable pointer going down on the left window, and it's coming
2789 // from a different device, the current gesture in the left window (pointer down) should first
2790 // be canceled.
2791 leftWindow->consumeMotionEvent(
2792 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002793 leftWindow->consumeMotionEvent(
2794 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2795 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2796 // current implementation.
2797 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2798 rightWindow->consumeMotionEvent(
2799 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2800
2801 leftWindow->assertNoEvents();
2802 rightWindow->assertNoEvents();
2803}
2804
2805/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002806 * Two windows: a window on the left and a window on the right.
2807 * Mouse is hovered on the left window and stylus is hovered on the right window.
2808 */
2809TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2811 sp<FakeWindowHandle> leftWindow =
2812 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2813 leftWindow->setFrame(Rect(0, 0, 200, 200));
2814
2815 sp<FakeWindowHandle> rightWindow =
2816 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2817 rightWindow->setFrame(Rect(200, 0, 400, 200));
2818
2819 mDispatcher->onWindowInfosChanged(
2820 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2821
2822 const int32_t stylusDeviceId = 3;
2823 const int32_t mouseDeviceId = 6;
2824
2825 // Start hovering over the left window
2826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2827 .deviceId(mouseDeviceId)
2828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2829 .build());
2830 leftWindow->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2832
2833 // Stylus hovered on right window
2834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2835 .deviceId(stylusDeviceId)
2836 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2837 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002838 rightWindow->consumeMotionEvent(
2839 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2840
2841 // Subsequent HOVER_MOVE events are dispatched correctly.
2842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2843 .deviceId(mouseDeviceId)
2844 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2845 .build());
2846 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002847 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002848
2849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2850 .deviceId(stylusDeviceId)
2851 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2852 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002853 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002854 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002855
2856 leftWindow->assertNoEvents();
2857 rightWindow->assertNoEvents();
2858}
2859
2860/**
2861 * Three windows: a window on the left and a window on the right.
2862 * And a spy window that's positioned above all of them.
2863 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2864 * Check the stream that's received by the spy.
2865 */
2866TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2868
2869 sp<FakeWindowHandle> spyWindow =
2870 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2871 spyWindow->setFrame(Rect(0, 0, 400, 400));
2872 spyWindow->setTrustedOverlay(true);
2873 spyWindow->setSpy(true);
2874
2875 sp<FakeWindowHandle> leftWindow =
2876 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2877 leftWindow->setFrame(Rect(0, 0, 200, 200));
2878
2879 sp<FakeWindowHandle> rightWindow =
2880 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2881
2882 rightWindow->setFrame(Rect(200, 0, 400, 200));
2883
2884 mDispatcher->onWindowInfosChanged(
2885 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2886
2887 const int32_t stylusDeviceId = 1;
2888 const int32_t touchDeviceId = 2;
2889
2890 // Stylus down on the left window
2891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2892 .deviceId(stylusDeviceId)
2893 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2894 .build());
2895 leftWindow->consumeMotionEvent(
2896 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2897 spyWindow->consumeMotionEvent(
2898 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2899
2900 // Touch down on the right window
2901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2902 .deviceId(touchDeviceId)
2903 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2904 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002905 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002906 rightWindow->consumeMotionEvent(
2907 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002908
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002909 // Spy window does not receive touch events, because stylus events take precedence, and it
2910 // already has an active stylus gesture.
2911
2912 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2914 .deviceId(stylusDeviceId)
2915 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2916 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002917 leftWindow->consumeMotionEvent(
2918 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2919 spyWindow->consumeMotionEvent(
2920 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002921
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002922 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2924 .deviceId(touchDeviceId)
2925 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2926 .build());
2927 rightWindow->consumeMotionEvent(
2928 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002929
2930 spyWindow->assertNoEvents();
2931 leftWindow->assertNoEvents();
2932 rightWindow->assertNoEvents();
2933}
2934
2935/**
2936 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2937 * both.
2938 * Check hover in left window and touch down in the right window.
2939 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002940 * At the same time, left and right should be getting independent streams of hovering and touch,
2941 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002942 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002943TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlockedByTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2945
2946 sp<FakeWindowHandle> spyWindow =
2947 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2948 spyWindow->setFrame(Rect(0, 0, 400, 400));
2949 spyWindow->setTrustedOverlay(true);
2950 spyWindow->setSpy(true);
2951
2952 sp<FakeWindowHandle> leftWindow =
2953 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2954 leftWindow->setFrame(Rect(0, 0, 200, 200));
2955
2956 sp<FakeWindowHandle> rightWindow =
2957 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2958 rightWindow->setFrame(Rect(200, 0, 400, 200));
2959
2960 mDispatcher->onWindowInfosChanged(
2961 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2962
2963 const int32_t stylusDeviceId = 1;
2964 const int32_t touchDeviceId = 2;
2965
2966 // Stylus hover on the left window
2967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2968 .deviceId(stylusDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2970 .build());
2971 leftWindow->consumeMotionEvent(
2972 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2973 spyWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2975
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002976 // Touch down on the right window. Spy doesn't receive this touch because it already has
2977 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2979 .deviceId(touchDeviceId)
2980 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2981 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002982 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002983 spyWindow->consumeMotionEvent(
2984 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2985 spyWindow->consumeMotionEvent(
2986 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2987 rightWindow->consumeMotionEvent(
2988 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2989
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002990 // Stylus movements continue. They should be delivered to the left window only.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2992 .deviceId(stylusDeviceId)
2993 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2994 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002995 leftWindow->consumeMotionEvent(
2996 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002997
2998 // Touch movements continue. They should be delivered to the right window and to the spy
2999 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3000 .deviceId(touchDeviceId)
3001 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3002 .build());
3003 spyWindow->consumeMotionEvent(
3004 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3005 rightWindow->consumeMotionEvent(
3006 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3007
3008 spyWindow->assertNoEvents();
3009 leftWindow->assertNoEvents();
3010 rightWindow->assertNoEvents();
3011}
3012
3013/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003014 * On a single window, use two different devices: mouse and touch.
3015 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3016 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3017 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3018 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3019 * represent a new gesture.
3020 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003021TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3023 sp<FakeWindowHandle> window =
3024 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3025 window->setFrame(Rect(0, 0, 400, 400));
3026
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003027 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003028
3029 const int32_t touchDeviceId = 4;
3030 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003031
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003032 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003033 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3034 .deviceId(touchDeviceId)
3035 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3036 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003037 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003038 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3039 .deviceId(touchDeviceId)
3040 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3041 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3042 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003043 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003044 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3045 .deviceId(touchDeviceId)
3046 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3047 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3048 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003049 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3050 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3051 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3052
3053 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3055 .deviceId(mouseDeviceId)
3056 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3057 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3058 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003059
3060 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003061 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003062 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3063
Prabir Pradhan678438e2023-04-13 19:32:51 +00003064 mDispatcher->notifyMotion(
3065 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3066 .deviceId(mouseDeviceId)
3067 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3068 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3069 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3070 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003071 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3072
3073 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003074 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3075 .deviceId(touchDeviceId)
3076 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3077 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3078 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003079 // Since we already canceled this touch gesture, it will be ignored until a completely new
3080 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3081 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3082 // However, mouse movements should continue to work.
3083 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3084 .deviceId(mouseDeviceId)
3085 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3086 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3087 .build());
3088 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3089
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003090 window->assertNoEvents();
3091}
3092
3093/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003094 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3095 * the injected event.
3096 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003097TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3099 sp<FakeWindowHandle> window =
3100 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3101 window->setFrame(Rect(0, 0, 400, 400));
3102
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003103 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003104
3105 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003106 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3107 // completion.
3108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003109 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003110 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3111 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003112 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003113 .build()));
3114 window->consumeMotionEvent(
3115 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3116
3117 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3118 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3120 .deviceId(touchDeviceId)
3121 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3122 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003123
3124 window->consumeMotionEvent(
3125 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3126 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3127}
3128
3129/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003130 * This test is similar to the test above, but the sequence of injected events is different.
3131 *
3132 * Two windows: a window on the left and a window on the right.
3133 * Mouse is hovered over the left window.
3134 * Next, we tap on the left window, where the cursor was last seen.
3135 *
3136 * After that, we inject one finger down onto the right window, and then a second finger down onto
3137 * the left window.
3138 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3139 * window (first), and then another on the left window (second).
3140 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3141 * In the buggy implementation, second finger down on the left window would cause a crash.
3142 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003143TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3145 sp<FakeWindowHandle> leftWindow =
3146 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3147 leftWindow->setFrame(Rect(0, 0, 200, 200));
3148
3149 sp<FakeWindowHandle> rightWindow =
3150 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3151 rightWindow->setFrame(Rect(200, 0, 400, 200));
3152
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003153 mDispatcher->onWindowInfosChanged(
3154 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003155
3156 const int32_t mouseDeviceId = 6;
3157 const int32_t touchDeviceId = 4;
3158 // Hover over the left window. Keep the cursor there.
3159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003160 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003161 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3162 AINPUT_SOURCE_MOUSE)
3163 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003164 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003165 .build()));
3166 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3167
3168 // Tap on left window
3169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003170 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003171 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3172 AINPUT_SOURCE_TOUCHSCREEN)
3173 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003174 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003175 .build()));
3176
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003179 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3180 AINPUT_SOURCE_TOUCHSCREEN)
3181 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003182 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003183 .build()));
3184 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3185 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3186 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3187
3188 // First finger down on right window
3189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003190 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003191 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3192 AINPUT_SOURCE_TOUCHSCREEN)
3193 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003194 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003195 .build()));
3196 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3197
3198 // Second finger down on the left window
3199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003200 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003201 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3202 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003203 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3204 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003205 .build()));
3206 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3207 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3208
3209 // No more events
3210 leftWindow->assertNoEvents();
3211 rightWindow->assertNoEvents();
3212}
3213
3214/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003215 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3216 * While the touch is down, new hover events from the stylus device should be ignored. After the
3217 * touch is gone, stylus hovering should start working again.
3218 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003219TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDroppedWhenTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3221 sp<FakeWindowHandle> window =
3222 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3223 window->setFrame(Rect(0, 0, 200, 200));
3224
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003225 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003226
3227 const int32_t stylusDeviceId = 5;
3228 const int32_t touchDeviceId = 4;
3229 // Start hovering with stylus
3230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003231 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003232 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003233 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003234 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003235 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003236 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003237
3238 // Finger down on the window
3239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003240 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003241 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003242 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003243 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003244 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003245 // The touch device should cause hover to stop!
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003246 window->consumeMotionEvent(
3247 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3248 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003249
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003250 // Continue hovering with stylus.
3251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003252 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003253 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3254 AINPUT_SOURCE_STYLUS)
3255 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003256 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003257 .build()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003258 // Hovers are now ignored
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003259
3260 // Lift up the finger
3261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003262 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003263 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3264 AINPUT_SOURCE_TOUCHSCREEN)
3265 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003266 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003267 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003268 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003269
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003271 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003272 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3273 AINPUT_SOURCE_STYLUS)
3274 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003275 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003276 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003277 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3278 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003279 window->assertNoEvents();
3280}
3281
3282/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003283 * A spy window above a window with no input channel.
3284 * Start hovering with a stylus device, and then tap with it.
3285 * Ensure spy window receives the entire sequence.
3286 */
3287TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3289 sp<FakeWindowHandle> spyWindow =
3290 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3291 spyWindow->setFrame(Rect(0, 0, 200, 200));
3292 spyWindow->setTrustedOverlay(true);
3293 spyWindow->setSpy(true);
3294 sp<FakeWindowHandle> window =
3295 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3296 window->setNoInputChannel(true);
3297 window->setFrame(Rect(0, 0, 200, 200));
3298
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003299 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003300
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003301 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003302 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3303 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3304 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003305 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3306 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3308 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3309 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003310 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3311
3312 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3314 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3315 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003316 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3317
3318 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003319 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3320 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3321 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003322 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3323
3324 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3326 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3327 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003328 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3329 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3332 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003333 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3334
3335 // No more events
3336 spyWindow->assertNoEvents();
3337 window->assertNoEvents();
3338}
3339
3340/**
3341 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3342 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3343 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3344 * While the mouse is down, new move events from the touch device should be ignored.
3345 */
3346TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3347 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3348 sp<FakeWindowHandle> spyWindow =
3349 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3350 spyWindow->setFrame(Rect(0, 0, 200, 200));
3351 spyWindow->setTrustedOverlay(true);
3352 spyWindow->setSpy(true);
3353 sp<FakeWindowHandle> window =
3354 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3355 window->setFrame(Rect(0, 0, 200, 200));
3356
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003357 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003358
3359 const int32_t mouseDeviceId = 7;
3360 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003361
3362 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003363 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3364 .deviceId(mouseDeviceId)
3365 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3366 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003367 spyWindow->consumeMotionEvent(
3368 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3369 window->consumeMotionEvent(
3370 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3371
3372 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3374 .deviceId(touchDeviceId)
3375 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3376 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003377 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3378 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3379 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3380 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3381
Prabir Pradhan678438e2023-04-13 19:32:51 +00003382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3383 .deviceId(touchDeviceId)
3384 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3385 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003386 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3387 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3388
3389 // Pilfer the stream
3390 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3391 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3392
Prabir Pradhan678438e2023-04-13 19:32:51 +00003393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3394 .deviceId(touchDeviceId)
3395 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3396 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003397 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3398
3399 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3401 .deviceId(mouseDeviceId)
3402 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3404 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003405
3406 spyWindow->consumeMotionEvent(
3407 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3408 spyWindow->consumeMotionEvent(
3409 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3410 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3411
Prabir Pradhan678438e2023-04-13 19:32:51 +00003412 mDispatcher->notifyMotion(
3413 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3414 .deviceId(mouseDeviceId)
3415 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3416 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3417 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3418 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003419 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3420 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3421
3422 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3424 .deviceId(mouseDeviceId)
3425 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3426 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3427 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003428 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3429 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3430
3431 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3433 .deviceId(touchDeviceId)
3434 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3435 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003436
3437 // No more events
3438 spyWindow->assertNoEvents();
3439 window->assertNoEvents();
3440}
3441
3442/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003443 * On the display, have a single window, and also an area where there's no window.
3444 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3445 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3446 */
3447TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3449 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003450 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003451
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003452 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003453
3454 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003455 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003456
3457 mDispatcher->waitForIdle();
3458 window->assertNoEvents();
3459
3460 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003461 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003462 mDispatcher->waitForIdle();
3463 window->consumeMotionDown();
3464}
3465
3466/**
3467 * Same test as above, but instead of touching the empty space, the first touch goes to
3468 * non-touchable window.
3469 */
3470TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3472 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003473 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003474 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3475 window1->setTouchable(false);
3476 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003477 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003478 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3479
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003480 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003481
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003482 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003483 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003484
3485 mDispatcher->waitForIdle();
3486 window1->assertNoEvents();
3487 window2->assertNoEvents();
3488
3489 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003490 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003491 mDispatcher->waitForIdle();
3492 window2->consumeMotionDown();
3493}
3494
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003495/**
3496 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3497 * to the event time of the first ACTION_DOWN sent to the particular window.
3498 */
3499TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3501 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003502 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003503 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3504 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003505 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003506 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3507
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003508 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003509
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003510 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003511 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003512
3513 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003514
3515 MotionEvent* motionEvent1 = window1->consumeMotion();
3516 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003517 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003518 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3519 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003520
3521 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003522 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003523 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003524 MotionEvent* motionEvent2 = window2->consumeMotion();
3525 ASSERT_NE(motionEvent2, nullptr);
3526 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003527 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003528 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003529
3530 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003531 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003532 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003533 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003534
3535 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003537 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003538 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003539
3540 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3541 window1->consumeMotionMove();
3542 window1->assertNoEvents();
3543
3544 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003545 mDispatcher->notifyMotion(
3546 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003547 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003548 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003549
Prabir Pradhan678438e2023-04-13 19:32:51 +00003550 mDispatcher->notifyMotion(
3551 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003552 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003553 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003554}
3555
Garfield Tandf26e862020-07-01 20:18:19 -07003556TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003558 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003559 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003560 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003561 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003562 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003563 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003564
3565 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3566
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003567 mDispatcher->onWindowInfosChanged(
3568 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003569
3570 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003571 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003572 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003573 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3574 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003575 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003576 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003577 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003578
3579 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003581 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003582 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3583 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003584 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003585 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003586 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3587 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003588
3589 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003592 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3593 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003594 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003595 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003596 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3597 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003598
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003600 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003601 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3602 AINPUT_SOURCE_MOUSE)
3603 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3604 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003605 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003606 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003607 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003608
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003610 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003611 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3612 AINPUT_SOURCE_MOUSE)
3613 .buttonState(0)
3614 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003615 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003616 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003617 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003618
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003620 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003621 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3622 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003623 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003624 .build()));
3625 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3626
3627 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003629 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003630 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3631 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003632 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003633 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003634 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003635
3636 // No more events
3637 windowLeft->assertNoEvents();
3638 windowRight->assertNoEvents();
3639}
3640
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003641/**
3642 * Put two fingers down (and don't release them) and click the mouse button.
3643 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3644 * currently active gesture should be canceled, and the new one should proceed.
3645 */
3646TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3648 sp<FakeWindowHandle> window =
3649 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3650 window->setFrame(Rect(0, 0, 600, 800));
3651
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003652 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003653
3654 const int32_t touchDeviceId = 4;
3655 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003656
3657 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3659 .deviceId(touchDeviceId)
3660 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3661 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003662
Prabir Pradhan678438e2023-04-13 19:32:51 +00003663 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3664 .deviceId(touchDeviceId)
3665 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3666 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003668 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3669 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3670
3671 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3673 .deviceId(mouseDeviceId)
3674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003677 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3678 WithPointerCount(2u)));
3679 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3680
Prabir Pradhan678438e2023-04-13 19:32:51 +00003681 mDispatcher->notifyMotion(
3682 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3683 .deviceId(mouseDeviceId)
3684 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3685 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3686 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3687 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003688 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3689
3690 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3691 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3693 .deviceId(touchDeviceId)
3694 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3695 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3696 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003697 window->assertNoEvents();
3698}
3699
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003700TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3702
3703 sp<FakeWindowHandle> spyWindow =
3704 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3705 spyWindow->setFrame(Rect(0, 0, 600, 800));
3706 spyWindow->setTrustedOverlay(true);
3707 spyWindow->setSpy(true);
3708 sp<FakeWindowHandle> window =
3709 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3710 window->setFrame(Rect(0, 0, 600, 800));
3711
3712 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003713 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003714
3715 // Send mouse cursor to the window
3716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003717 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003718 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3719 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003721 .build()));
3722
3723 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3724 WithSource(AINPUT_SOURCE_MOUSE)));
3725 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3726 WithSource(AINPUT_SOURCE_MOUSE)));
3727
3728 window->assertNoEvents();
3729 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003730}
3731
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003732TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3734
3735 sp<FakeWindowHandle> spyWindow =
3736 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3737 spyWindow->setFrame(Rect(0, 0, 600, 800));
3738 spyWindow->setTrustedOverlay(true);
3739 spyWindow->setSpy(true);
3740 sp<FakeWindowHandle> window =
3741 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3742 window->setFrame(Rect(0, 0, 600, 800));
3743
3744 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003745 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003746
3747 // Send mouse cursor to the window
3748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003749 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003750 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3751 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003752 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003753 .build()));
3754
3755 // Move mouse cursor
3756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003757 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003758 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3759 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003761 .build()));
3762
3763 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3764 WithSource(AINPUT_SOURCE_MOUSE)));
3765 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3766 WithSource(AINPUT_SOURCE_MOUSE)));
3767 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3768 WithSource(AINPUT_SOURCE_MOUSE)));
3769 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3770 WithSource(AINPUT_SOURCE_MOUSE)));
3771 // Touch down on the window
3772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003773 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003774 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3775 AINPUT_SOURCE_TOUCHSCREEN)
3776 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003777 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003778 .build()));
3779 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3780 WithSource(AINPUT_SOURCE_MOUSE)));
3781 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3782 WithSource(AINPUT_SOURCE_MOUSE)));
3783 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3784 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3785 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3786 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3787
3788 // pilfer the motion, retaining the gesture on the spy window.
3789 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3790 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3791 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3792
3793 // Touch UP on the window
3794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003795 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003796 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3797 AINPUT_SOURCE_TOUCHSCREEN)
3798 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003799 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003800 .build()));
3801 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3802 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3803
3804 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3805 // to send a new gesture. It should again go to both windows (spy and the window below), just
3806 // like the first gesture did, before pilfering. The window configuration has not changed.
3807
3808 // One more tap - DOWN
3809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003810 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003811 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3812 AINPUT_SOURCE_TOUCHSCREEN)
3813 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003814 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003815 .build()));
3816 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3817 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3818 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3819 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3820
3821 // Touch UP on the window
3822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003823 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003824 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3825 AINPUT_SOURCE_TOUCHSCREEN)
3826 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003827 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003828 .build()));
3829 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3830 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3831 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3832 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3833
3834 window->assertNoEvents();
3835 spyWindow->assertNoEvents();
3836}
3837
Garfield Tandf26e862020-07-01 20:18:19 -07003838// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3839// directly in this test.
3840TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003842 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003843 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003844 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003845
3846 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3847
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003848 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003849
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003851 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003852 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3853 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003854 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003855 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003856 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003857 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003859 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003860 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3861 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003862 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003863 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003864 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3865 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003866
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003868 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003869 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3870 AINPUT_SOURCE_MOUSE)
3871 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3872 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003873 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003874 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003875 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003876
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003878 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003879 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3880 AINPUT_SOURCE_MOUSE)
3881 .buttonState(0)
3882 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003883 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003884 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003885 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003886
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003888 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003889 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3890 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003891 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003892 .build()));
3893 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3894
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003895 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3896 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3897 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003898 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003899 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3900 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003901 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003902 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003903 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003904}
3905
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003906/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003907 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3908 * is generated.
3909 */
3910TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3911 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3912 sp<FakeWindowHandle> window =
3913 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3914 window->setFrame(Rect(0, 0, 1200, 800));
3915
3916 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3917
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003918 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003919
3920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003921 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003922 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3923 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003924 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003925 .build()));
3926 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3927
3928 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003929 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003930 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3931}
3932
3933/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003934 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3935 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003936TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
3937 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
3938 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07003939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3940 sp<FakeWindowHandle> window =
3941 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3942 window->setFrame(Rect(0, 0, 1200, 800));
3943
3944 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3945
3946 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3947
3948 MotionEventBuilder hoverEnterBuilder =
3949 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3951 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3953 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3955 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3956 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3957 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3958}
3959
3960/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003961 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3962 */
3963TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3964 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3965 sp<FakeWindowHandle> window =
3966 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3967 window->setFrame(Rect(0, 0, 100, 100));
3968
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003969 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003970
3971 const int32_t mouseDeviceId = 7;
3972 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003973
3974 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3976 .deviceId(mouseDeviceId)
3977 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3978 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003979 window->consumeMotionEvent(
3980 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3981
3982 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003983 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3984 .deviceId(touchDeviceId)
3985 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3986 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003987
3988 window->consumeMotionEvent(
3989 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3990 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3991}
3992
3993/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003994 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003995 * The tap causes a HOVER_EXIT event to be generated because the current event
3996 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003997 */
3998TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3999 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4000 sp<FakeWindowHandle> window =
4001 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4002 window->setFrame(Rect(0, 0, 100, 100));
4003
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004004 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4006 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4007 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004008 ASSERT_NO_FATAL_FAILURE(
4009 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4010 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004011
4012 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4014 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4015 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004016 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004017 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4018 WithSource(AINPUT_SOURCE_MOUSE))));
4019
4020 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004021 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4022 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4023
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004024 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4025 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4026 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004027 ASSERT_NO_FATAL_FAILURE(
4028 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4029 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4030}
4031
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004032TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4033 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4034 sp<FakeWindowHandle> windowDefaultDisplay =
4035 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4036 ADISPLAY_ID_DEFAULT);
4037 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4038 sp<FakeWindowHandle> windowSecondDisplay =
4039 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4040 SECOND_DISPLAY_ID);
4041 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4042
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004043 mDispatcher->onWindowInfosChanged(
4044 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004045
4046 // Set cursor position in window in default display and check that hover enter and move
4047 // events are generated.
4048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004049 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004050 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4051 AINPUT_SOURCE_MOUSE)
4052 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004053 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004054 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004055 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004056
4057 // Remove all windows in secondary display and check that no event happens on window in
4058 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004059 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4060
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004061 windowDefaultDisplay->assertNoEvents();
4062
4063 // Move cursor position in window in default display and check that only hover move
4064 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004065 mDispatcher->onWindowInfosChanged(
4066 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004068 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004069 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4070 AINPUT_SOURCE_MOUSE)
4071 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004072 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004073 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004074 windowDefaultDisplay->consumeMotionEvent(
4075 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4076 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004077 windowDefaultDisplay->assertNoEvents();
4078}
4079
Garfield Tan00f511d2019-06-12 16:55:40 -07004080TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004082
4083 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004084 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004085 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004086 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004087 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004088 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004089
4090 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4091
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004092 mDispatcher->onWindowInfosChanged(
4093 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004094
4095 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4096 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004098 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004099 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004100 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004101 windowRight->assertNoEvents();
4102}
4103
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004104TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004105 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004106 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4107 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004108 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004110 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004111 setFocusedWindow(window);
4112
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004113 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004114
Prabir Pradhan678438e2023-04-13 19:32:51 +00004115 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004116
4117 // Window should receive key down event.
4118 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4119
4120 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4121 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004122 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004123 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004124 AKEY_EVENT_FLAG_CANCELED);
4125}
4126
4127TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004128 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004129 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4130 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004131
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004132 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004133
Prabir Pradhan678438e2023-04-13 19:32:51 +00004134 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4135 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004136
4137 // Window should receive motion down event.
4138 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4139
4140 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4141 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004142 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004143 window->consumeMotionEvent(
4144 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004145}
4146
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004147TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4149 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4150 "Fake Window", ADISPLAY_ID_DEFAULT);
4151
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004152 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004153
4154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4155 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4156 .build());
4157
4158 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4159
4160 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4161 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4162 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4163
4164 // After the device has been reset, a new hovering stream can be sent to the window
4165 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4166 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4167 .build());
4168 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4169}
4170
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004171TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004173 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4174 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004175 window->setFocusable(true);
4176
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004177 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004178 setFocusedWindow(window);
4179
4180 window->consumeFocusEvent(true);
4181
Prabir Pradhan678438e2023-04-13 19:32:51 +00004182 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004183 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4184 const nsecs_t injectTime = keyArgs.eventTime;
4185 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004186 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004187 // The dispatching time should be always greater than or equal to intercept key timeout.
4188 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4189 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4190 std::chrono::nanoseconds(interceptKeyTimeout).count());
4191}
4192
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004193/**
4194 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4195 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004196TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004198 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4199 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004200 window->setFocusable(true);
4201
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004202 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004203 setFocusedWindow(window);
4204
4205 window->consumeFocusEvent(true);
4206
Prabir Pradhan678438e2023-04-13 19:32:51 +00004207 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004208 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004209
4210 // Set a value that's significantly larger than the default consumption timeout. If the
4211 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4212 mFakePolicy->setInterceptKeyTimeout(600ms);
4213 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4214 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004215 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4216}
4217
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004218/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004219 * Two windows. First is a regular window. Second does not overlap with the first, and has
4220 * WATCH_OUTSIDE_TOUCH.
4221 * Both windows are owned by the same UID.
4222 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4223 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4224 */
4225TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004227 sp<FakeWindowHandle> window =
4228 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004229 window->setFrame(Rect{0, 0, 100, 100});
4230
4231 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004232 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004233 ADISPLAY_ID_DEFAULT);
4234 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4235 outsideWindow->setWatchOutsideTouch(true);
4236 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004237 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004238
4239 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004240 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4241 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4242 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004243 window->consumeMotionDown();
4244 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4245 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4246 outsideWindow->consumeMotionEvent(
4247 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4248}
4249
4250/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004251 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4252 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4253 * ACTION_OUTSIDE event is sent per gesture.
4254 */
4255TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4256 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004258 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4259 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004260 window->setWatchOutsideTouch(true);
4261 window->setFrame(Rect{0, 0, 100, 100});
4262 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004263 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4264 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004265 secondWindow->setFrame(Rect{100, 100, 200, 200});
4266 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004267 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4268 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004269 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004270 mDispatcher->onWindowInfosChanged(
4271 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004272
4273 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004274 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4275 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4276 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004277 window->assertNoEvents();
4278 secondWindow->assertNoEvents();
4279
4280 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4281 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004282 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4283 ADISPLAY_ID_DEFAULT,
4284 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004285 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4286 window->consumeMotionEvent(
4287 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004288 secondWindow->consumeMotionDown();
4289 thirdWindow->assertNoEvents();
4290
4291 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4292 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004293 mDispatcher->notifyMotion(
4294 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4295 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004296 window->assertNoEvents();
4297 secondWindow->consumeMotionMove();
4298 thirdWindow->consumeMotionDown();
4299}
4300
Prabir Pradhan814fe082022-07-22 20:22:18 +00004301TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4302 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004303 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4304 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004305 window->setFocusable(true);
4306
Patrick Williamsd828f302023-04-28 17:52:08 -05004307 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004308 setFocusedWindow(window);
4309
4310 window->consumeFocusEvent(true);
4311
Prabir Pradhan678438e2023-04-13 19:32:51 +00004312 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4313 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4314 mDispatcher->notifyKey(keyDown);
4315 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004316
4317 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4318 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4319
4320 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004321 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004322
4323 window->consumeFocusEvent(false);
4324
Prabir Pradhan678438e2023-04-13 19:32:51 +00004325 mDispatcher->notifyKey(keyDown);
4326 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004327 window->assertNoEvents();
4328}
4329
Arthur Hung96483742022-11-15 03:30:48 +00004330TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4332 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4333 "Fake Window", ADISPLAY_ID_DEFAULT);
4334 // Ensure window is non-split and have some transform.
4335 window->setPreventSplitting(true);
4336 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004337 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004338
4339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004340 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004341 {50, 50}))
4342 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4343 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4344
4345 const MotionEvent secondFingerDownEvent =
4346 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4347 .displayId(ADISPLAY_ID_DEFAULT)
4348 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004349 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4350 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004351 .build();
4352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004353 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004354 InputEventInjectionSync::WAIT_FOR_RESULT))
4355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4356
4357 const MotionEvent* event = window->consumeMotion();
4358 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4359 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4360 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4361 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4362 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4363}
4364
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004365/**
4366 * Two windows: a splittable and a non-splittable.
4367 * The non-splittable window shouldn't receive any "incomplete" gestures.
4368 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4369 * The second pointer should be dropped because the initial window is splittable, so it won't get
4370 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4371 * "incomplete" gestures.
4372 */
4373TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4375 sp<FakeWindowHandle> leftWindow =
4376 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4377 ADISPLAY_ID_DEFAULT);
4378 leftWindow->setPreventSplitting(false);
4379 leftWindow->setFrame(Rect(0, 0, 100, 100));
4380 sp<FakeWindowHandle> rightWindow =
4381 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4382 ADISPLAY_ID_DEFAULT);
4383 rightWindow->setPreventSplitting(true);
4384 rightWindow->setFrame(Rect(100, 100, 200, 200));
4385 mDispatcher->onWindowInfosChanged(
4386 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4387
4388 // Touch down on left, splittable window
4389 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4390 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4391 .build());
4392 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4393
4394 mDispatcher->notifyMotion(
4395 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4396 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4397 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4398 .build());
4399 leftWindow->assertNoEvents();
4400 rightWindow->assertNoEvents();
4401}
4402
Harry Cuttsb166c002023-05-09 13:06:05 +00004403TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4405 sp<FakeWindowHandle> window =
4406 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4407 window->setFrame(Rect(0, 0, 400, 400));
4408 sp<FakeWindowHandle> trustedOverlay =
4409 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4410 ADISPLAY_ID_DEFAULT);
4411 trustedOverlay->setSpy(true);
4412 trustedOverlay->setTrustedOverlay(true);
4413
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004414 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004415
4416 // Start a three-finger touchpad swipe
4417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4418 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4419 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4420 .build());
4421 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4422 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4423 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4424 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4425 .build());
4426 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4427 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4428 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4429 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4430 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4431 .build());
4432
4433 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4434 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4435 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4436
4437 // Move the swipe a bit
4438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4439 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4440 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4441 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4442 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4443 .build());
4444
4445 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4446
4447 // End the swipe
4448 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4449 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4450 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4451 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4452 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4453 .build());
4454 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4455 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4456 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4457 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4458 .build());
4459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4460 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4461 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4462 .build());
4463
4464 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4465 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4466 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4467
4468 window->assertNoEvents();
4469}
4470
4471TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4473 sp<FakeWindowHandle> window =
4474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4475 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004476 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004477
4478 // Start a three-finger touchpad swipe
4479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4480 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4481 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4482 .build());
4483 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4484 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4485 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4486 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4487 .build());
4488 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4489 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4490 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4491 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4492 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4493 .build());
4494
4495 // Move the swipe a bit
4496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4497 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4498 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4499 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4500 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4501 .build());
4502
4503 // End the swipe
4504 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4505 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4506 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4507 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4508 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4509 .build());
4510 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4511 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4512 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4513 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4514 .build());
4515 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4516 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4517 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4518 .build());
4519
4520 window->assertNoEvents();
4521}
4522
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004523/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004524 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4525 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004526 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004527 */
4528TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4530 sp<FakeWindowHandle> window =
4531 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4532 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004533 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004534
4535 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4537 .downTime(baseTime + 10)
4538 .eventTime(baseTime + 10)
4539 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4540 .build());
4541
4542 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4543
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004544 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004545 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004546
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004547 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004548
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004549 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4550 .downTime(baseTime + 10)
4551 .eventTime(baseTime + 30)
4552 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4553 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4554 .build());
4555
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004556 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4557
4558 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004559 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4560 .downTime(baseTime + 10)
4561 .eventTime(baseTime + 40)
4562 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4563 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4564 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004565
4566 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4567
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4569 .downTime(baseTime + 10)
4570 .eventTime(baseTime + 50)
4571 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4572 .build());
4573
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004574 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4575
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4577 .downTime(baseTime + 60)
4578 .eventTime(baseTime + 60)
4579 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4580 .build());
4581
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004582 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004583}
4584
4585/**
Hu Guo771a7692023-09-17 20:51:08 +08004586 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4587 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4588 * its coordinates should be converted by the transform of the windows of target screen.
4589 */
4590TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4591 // This case will create a window and a spy window on the default display and mirror
4592 // window on the second display. cancel event is sent through spy window pilferPointers
4593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4594
4595 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4596 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4597 spyWindowDefaultDisplay->setTrustedOverlay(true);
4598 spyWindowDefaultDisplay->setSpy(true);
4599
4600 sp<FakeWindowHandle> windowDefaultDisplay =
4601 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4602 ADISPLAY_ID_DEFAULT);
4603 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4604
4605 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4606 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4607
4608 // Add the windows to the dispatcher
4609 mDispatcher->onWindowInfosChanged(
4610 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4611 *windowSecondDisplay->getInfo()},
4612 {},
4613 0,
4614 0});
4615
4616 // Send down to ADISPLAY_ID_DEFAULT
4617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4618 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4619 {100, 100}))
4620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4621
4622 spyWindowDefaultDisplay->consumeMotionDown();
4623 windowDefaultDisplay->consumeMotionDown();
4624
4625 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4626
4627 // windowDefaultDisplay gets cancel
4628 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4629 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4630
4631 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4632 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4633 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4634 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4635 EXPECT_EQ(100, event->getX(0));
4636 EXPECT_EQ(100, event->getY(0));
4637}
4638
4639/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004640 * Ensure the correct coordinate spaces are used by InputDispatcher.
4641 *
4642 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4643 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4644 * space.
4645 */
4646class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4647public:
4648 void SetUp() override {
4649 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004650 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004651 }
4652
4653 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4654 gui::DisplayInfo info;
4655 info.displayId = displayId;
4656 info.transform = transform;
4657 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004658 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004659 }
4660
4661 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4662 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004663 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004664 }
4665
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004666 void removeAllWindowsAndDisplays() {
4667 mDisplayInfos.clear();
4668 mWindowInfos.clear();
4669 }
4670
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004671 // Set up a test scenario where the display has a scaled projection and there are two windows
4672 // on the display.
4673 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4674 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4675 // respectively.
4676 ui::Transform displayTransform;
4677 displayTransform.set(2, 0, 0, 4);
4678 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4679
4680 std::shared_ptr<FakeApplicationHandle> application =
4681 std::make_shared<FakeApplicationHandle>();
4682
4683 // Add two windows to the display. Their frames are represented in the display space.
4684 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004685 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4686 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004687 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4688 addWindow(firstWindow);
4689
4690 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004691 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4692 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004693 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4694 addWindow(secondWindow);
4695 return {std::move(firstWindow), std::move(secondWindow)};
4696 }
4697
4698private:
4699 std::vector<gui::DisplayInfo> mDisplayInfos;
4700 std::vector<gui::WindowInfo> mWindowInfos;
4701};
4702
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004703TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004704 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4705 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004706 // selected so that if the hit test was performed with the point and the bounds being in
4707 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004708 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4709 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4710 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004711
4712 firstWindow->consumeMotionDown();
4713 secondWindow->assertNoEvents();
4714}
4715
4716// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4717// the event should be treated as being in the logical display space.
4718TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4719 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4720 // Send down to the first window. The point is represented in the logical display space. The
4721 // point is selected so that if the hit test was done in logical display space, then it would
4722 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004723 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004724 PointF{75 * 2, 55 * 4});
4725
4726 firstWindow->consumeMotionDown();
4727 secondWindow->assertNoEvents();
4728}
4729
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004730// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4731// event should be treated as being in the logical display space.
4732TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4733 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4734
4735 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4736 ui::Transform injectedEventTransform;
4737 injectedEventTransform.set(matrix);
4738 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4739 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4740
4741 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4742 .displayId(ADISPLAY_ID_DEFAULT)
4743 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004744 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004745 .x(untransformedPoint.x)
4746 .y(untransformedPoint.y))
4747 .build();
4748 event.transform(matrix);
4749
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004750 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004751 InputEventInjectionSync::WAIT_FOR_RESULT);
4752
4753 firstWindow->consumeMotionDown();
4754 secondWindow->assertNoEvents();
4755}
4756
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004757TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4758 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4759
4760 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4762 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4763 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004764
4765 firstWindow->assertNoEvents();
4766 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004767 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004768 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4769
4770 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4771 EXPECT_EQ(300, event->getRawX(0));
4772 EXPECT_EQ(880, event->getRawY(0));
4773
4774 // Ensure that the x and y values are in the window's coordinate space.
4775 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4776 // the logical display space. This will be the origin of the window space.
4777 EXPECT_EQ(100, event->getX(0));
4778 EXPECT_EQ(80, event->getY(0));
4779}
4780
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004781TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4782 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4783 // The monitor will always receive events in the logical display's coordinate space, because
4784 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004785 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004786
4787 // Send down to the first window.
4788 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4789 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4790 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4791 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4792
4793 // Second pointer goes down on second window.
4794 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4795 ADISPLAY_ID_DEFAULT,
4796 {PointF{50, 100}, PointF{150, 220}}));
4797 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4798 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4799 {1, PointF{300, 880}}};
4800 monitor.consumeMotionEvent(
4801 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4802
4803 mDispatcher->cancelCurrentTouch();
4804
4805 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4806 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4807 monitor.consumeMotionEvent(
4808 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4809}
4810
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004811TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4812 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4813
4814 // Send down to the first window.
4815 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4816 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4817 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4818
4819 // The pointer is transferred to the second window, and the second window receives it in the
4820 // correct coordinate space.
4821 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4822 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4823 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4824}
4825
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004826TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4827 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4828
4829 // Send hover move to the second window, and ensure it shows up as hover enter.
4830 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4831 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4832 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4833 WithCoords(100, 80), WithRawCoords(300, 880)));
4834
4835 // Touch down at the same location and ensure a hover exit is synthesized.
4836 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4837 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4838 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4839 WithRawCoords(300, 880)));
4840 secondWindow->consumeMotionEvent(
4841 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4842 secondWindow->assertNoEvents();
4843 firstWindow->assertNoEvents();
4844}
4845
Prabir Pradhan453ae732023-10-13 14:30:14 +00004846// Same as above, but while the window is being mirrored.
4847TEST_F(InputDispatcherDisplayProjectionTest,
4848 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4849 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4850
4851 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4852 ui::Transform secondDisplayTransform;
4853 secondDisplayTransform.set(matrix);
4854 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4855
4856 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4857 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4858 addWindow(secondWindowClone);
4859
4860 // Send hover move to the second window, and ensure it shows up as hover enter.
4861 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4862 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4863 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4864 WithCoords(100, 80), WithRawCoords(300, 880)));
4865
4866 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4867 // display.
4868 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4869 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4870 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4871 WithRawCoords(300, 880)));
4872 secondWindow->consumeMotionEvent(
4873 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4874 secondWindow->assertNoEvents();
4875 firstWindow->assertNoEvents();
4876}
4877
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004878TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4879 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4880
4881 // Send hover enter to second window
4882 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4883 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4884 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4885 WithCoords(100, 80), WithRawCoords(300, 880)));
4886
4887 mDispatcher->cancelCurrentTouch();
4888
4889 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4890 WithRawCoords(300, 880)));
4891 secondWindow->assertNoEvents();
4892 firstWindow->assertNoEvents();
4893}
4894
Prabir Pradhan453ae732023-10-13 14:30:14 +00004895// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004896TEST_F(InputDispatcherDisplayProjectionTest,
4897 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4898 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4899
4900 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4901 ui::Transform secondDisplayTransform;
4902 secondDisplayTransform.set(matrix);
4903 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4904
4905 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4906 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4907 addWindow(secondWindowClone);
4908
4909 // Send hover enter to second window
4910 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4911 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4912 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4913 WithCoords(100, 80), WithRawCoords(300, 880),
4914 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4915
4916 mDispatcher->cancelCurrentTouch();
4917
4918 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4919 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4920 WithRawCoords(300, 880),
4921 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4922 secondWindow->assertNoEvents();
4923 firstWindow->assertNoEvents();
4924}
4925
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004926/** Ensure consistent behavior of InputDispatcher in all orientations. */
4927class InputDispatcherDisplayOrientationFixture
4928 : public InputDispatcherDisplayProjectionTest,
4929 public ::testing::WithParamInterface<ui::Rotation> {};
4930
4931// This test verifies the touchable region of a window for all rotations of the display by tapping
4932// in different locations on the display, specifically points close to the four corners of a
4933// window.
4934TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4935 constexpr static int32_t displayWidth = 400;
4936 constexpr static int32_t displayHeight = 800;
4937
4938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4939
4940 const auto rotation = GetParam();
4941
4942 // Set up the display with the specified rotation.
4943 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4944 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4945 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4946 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4947 logicalDisplayWidth, logicalDisplayHeight);
4948 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4949
4950 // Create a window with its bounds determined in the logical display.
4951 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4952 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4953 sp<FakeWindowHandle> window =
4954 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4955 window->setFrame(frameInDisplay, displayTransform);
4956 addWindow(window);
4957
4958 // The following points in logical display space should be inside the window.
4959 static const std::array<vec2, 4> insidePoints{
4960 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4961 for (const auto pointInsideWindow : insidePoints) {
4962 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4963 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004964 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4965 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4966 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004967 window->consumeMotionDown();
4968
Prabir Pradhan678438e2023-04-13 19:32:51 +00004969 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4970 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4971 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004972 window->consumeMotionUp();
4973 }
4974
4975 // The following points in logical display space should be outside the window.
4976 static const std::array<vec2, 5> outsidePoints{
4977 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4978 for (const auto pointOutsideWindow : outsidePoints) {
4979 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4980 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004981 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4982 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4983 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004984
Prabir Pradhan678438e2023-04-13 19:32:51 +00004985 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4986 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4987 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004988 }
4989 window->assertNoEvents();
4990}
4991
4992// Run the precision tests for all rotations.
4993INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4994 InputDispatcherDisplayOrientationFixture,
4995 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4996 ui::ROTATION_270),
4997 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4998 return ftl::enum_string(testParamInfo.param);
4999 });
5000
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005001using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5002 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005003
5004class TransferTouchFixture : public InputDispatcherTest,
5005 public ::testing::WithParamInterface<TransferFunction> {};
5006
5007TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005009
5010 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005011 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005012 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5013 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005014 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005015 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005016 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5017 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005018 sp<FakeWindowHandle> wallpaper =
5019 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5020 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005021 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005022 mDispatcher->onWindowInfosChanged(
5023 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005024
5025 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005026 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5027 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005028
Svet Ganov5d3bc372020-01-26 23:11:07 -08005029 // Only the first window should get the down event
5030 firstWindow->consumeMotionDown();
5031 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005032 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005033
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005034 // Transfer touch to the second window
5035 TransferFunction f = GetParam();
5036 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5037 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005038 // The first window gets cancel and the second gets down
5039 firstWindow->consumeMotionCancel();
5040 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005041 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005042
5043 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005044 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5045 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005046 // The first window gets no events and the second gets up
5047 firstWindow->assertNoEvents();
5048 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005049 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005050}
5051
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005052/**
5053 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5054 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5055 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5056 * natural to the user.
5057 * In this test, we are sending a pointer to both spy window and first window. We then try to
5058 * transfer touch to the second window. The dispatcher should identify the first window as the
5059 * one that should lose the gesture, and therefore the action should be to move the gesture from
5060 * the first window to the second.
5061 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5062 * the other API, as well.
5063 */
5064TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5065 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5066
5067 // Create a couple of windows + a spy window
5068 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005069 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005070 spyWindow->setTrustedOverlay(true);
5071 spyWindow->setSpy(true);
5072 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005073 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005074 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005075 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005076
5077 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005078 mDispatcher->onWindowInfosChanged(
5079 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005080
5081 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005082 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5083 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005084 // Only the first window and spy should get the down event
5085 spyWindow->consumeMotionDown();
5086 firstWindow->consumeMotionDown();
5087
5088 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5089 // if f === 'transferTouch'.
5090 TransferFunction f = GetParam();
5091 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5092 ASSERT_TRUE(success);
5093 // The first window gets cancel and the second gets down
5094 firstWindow->consumeMotionCancel();
5095 secondWindow->consumeMotionDown();
5096
5097 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005098 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5099 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005100 // The first window gets no events and the second+spy get up
5101 firstWindow->assertNoEvents();
5102 spyWindow->consumeMotionUp();
5103 secondWindow->consumeMotionUp();
5104}
5105
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005106TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005107 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005108
5109 PointF touchPoint = {10, 10};
5110
5111 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005112 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005113 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5114 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005115 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005116 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005117 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5118 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005119 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005120
5121 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005122 mDispatcher->onWindowInfosChanged(
5123 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005124
5125 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005126 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5127 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5128 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005129 // Only the first window should get the down event
5130 firstWindow->consumeMotionDown();
5131 secondWindow->assertNoEvents();
5132
5133 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005134 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5135 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005136 // Only the first window should get the pointer down event
5137 firstWindow->consumeMotionPointerDown(1);
5138 secondWindow->assertNoEvents();
5139
5140 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005141 TransferFunction f = GetParam();
5142 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5143 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005144 // The first window gets cancel and the second gets down and pointer down
5145 firstWindow->consumeMotionCancel();
5146 secondWindow->consumeMotionDown();
5147 secondWindow->consumeMotionPointerDown(1);
5148
5149 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005150 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5151 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005152 // The first window gets nothing and the second gets pointer up
5153 firstWindow->assertNoEvents();
5154 secondWindow->consumeMotionPointerUp(1);
5155
5156 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005157 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5158 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005159 // The first window gets nothing and the second gets up
5160 firstWindow->assertNoEvents();
5161 secondWindow->consumeMotionUp();
5162}
5163
Arthur Hungc539dbb2022-12-08 07:45:36 +00005164TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5166
5167 // Create a couple of windows
5168 sp<FakeWindowHandle> firstWindow =
5169 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5170 ADISPLAY_ID_DEFAULT);
5171 firstWindow->setDupTouchToWallpaper(true);
5172 sp<FakeWindowHandle> secondWindow =
5173 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5174 ADISPLAY_ID_DEFAULT);
5175 secondWindow->setDupTouchToWallpaper(true);
5176
5177 sp<FakeWindowHandle> wallpaper1 =
5178 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5179 wallpaper1->setIsWallpaper(true);
5180
5181 sp<FakeWindowHandle> wallpaper2 =
5182 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5183 wallpaper2->setIsWallpaper(true);
5184 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005185 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5186 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5187 {},
5188 0,
5189 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005190
5191 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005192 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5193 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005194
5195 // Only the first window should get the down event
5196 firstWindow->consumeMotionDown();
5197 secondWindow->assertNoEvents();
5198 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5199 wallpaper2->assertNoEvents();
5200
5201 // Transfer touch focus to the second window
5202 TransferFunction f = GetParam();
5203 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5204 ASSERT_TRUE(success);
5205
5206 // The first window gets cancel and the second gets down
5207 firstWindow->consumeMotionCancel();
5208 secondWindow->consumeMotionDown();
5209 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5210 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5211
5212 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005213 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5214 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005215 // The first window gets no events and the second gets up
5216 firstWindow->assertNoEvents();
5217 secondWindow->consumeMotionUp();
5218 wallpaper1->assertNoEvents();
5219 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5220}
5221
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005222// For the cases of single pointer touch and two pointers non-split touch, the api's
5223// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5224// for the case where there are multiple pointers split across several windows.
5225INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5226 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005227 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5228 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005229 return dispatcher->transferTouch(destChannelToken,
5230 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005231 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005232 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5233 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005234 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005235 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005236 }));
5237
Svet Ganov5d3bc372020-01-26 23:11:07 -08005238TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005239 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005240
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005241 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005242 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5243 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005244 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005245
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005246 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005247 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5248 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005249 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005250
5251 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005252 mDispatcher->onWindowInfosChanged(
5253 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005254
5255 PointF pointInFirst = {300, 200};
5256 PointF pointInSecond = {300, 600};
5257
5258 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005259 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5260 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5261 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005262 // Only the first window should get the down event
5263 firstWindow->consumeMotionDown();
5264 secondWindow->assertNoEvents();
5265
5266 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005267 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5268 ADISPLAY_ID_DEFAULT,
5269 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005270 // The first window gets a move and the second a down
5271 firstWindow->consumeMotionMove();
5272 secondWindow->consumeMotionDown();
5273
5274 // Transfer touch focus to the second window
5275 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5276 // The first window gets cancel and the new gets pointer down (it already saw down)
5277 firstWindow->consumeMotionCancel();
5278 secondWindow->consumeMotionPointerDown(1);
5279
5280 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005281 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5282 ADISPLAY_ID_DEFAULT,
5283 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005284 // The first window gets nothing and the second gets pointer up
5285 firstWindow->assertNoEvents();
5286 secondWindow->consumeMotionPointerUp(1);
5287
5288 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005289 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5290 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005291 // The first window gets nothing and the second gets up
5292 firstWindow->assertNoEvents();
5293 secondWindow->consumeMotionUp();
5294}
5295
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005296// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5297// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5298// touch is not supported, so the touch should continue on those windows and the transferred-to
5299// window should get nothing.
5300TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5302
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005303 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005304 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5305 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005306 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005307
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005308 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005309 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5310 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005311 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005312
5313 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005314 mDispatcher->onWindowInfosChanged(
5315 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005316
5317 PointF pointInFirst = {300, 200};
5318 PointF pointInSecond = {300, 600};
5319
5320 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005321 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5322 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5323 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005324 // Only the first window should get the down event
5325 firstWindow->consumeMotionDown();
5326 secondWindow->assertNoEvents();
5327
5328 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005329 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5330 ADISPLAY_ID_DEFAULT,
5331 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005332 // The first window gets a move and the second a down
5333 firstWindow->consumeMotionMove();
5334 secondWindow->consumeMotionDown();
5335
5336 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005337 const bool transferred =
5338 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005339 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5340 ASSERT_FALSE(transferred);
5341 firstWindow->assertNoEvents();
5342 secondWindow->assertNoEvents();
5343
5344 // The rest of the dispatch should proceed as normal
5345 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005346 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5347 ADISPLAY_ID_DEFAULT,
5348 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005349 // The first window gets MOVE and the second gets pointer up
5350 firstWindow->consumeMotionMove();
5351 secondWindow->consumeMotionUp();
5352
5353 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005354 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5355 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005356 // The first window gets nothing and the second gets up
5357 firstWindow->consumeMotionUp();
5358 secondWindow->assertNoEvents();
5359}
5360
Arthur Hungabbb9d82021-09-01 14:52:30 +00005361// This case will create two windows and one mirrored window on the default display and mirror
5362// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5363// the windows info of second display before default display.
5364TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5366 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005367 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005368 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005369 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005370 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005371 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005372
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005373 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005374 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005375
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005376 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005377 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005378
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005379 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005380 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005381
5382 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005383 mDispatcher->onWindowInfosChanged(
5384 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5385 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5386 *secondWindowInPrimary->getInfo()},
5387 {},
5388 0,
5389 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005390
5391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005392 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005393 {50, 50}))
5394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5395
5396 // Window should receive motion event.
5397 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5398
5399 // Transfer touch focus
5400 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5401 secondWindowInPrimary->getToken()));
5402 // The first window gets cancel.
5403 firstWindowInPrimary->consumeMotionCancel();
5404 secondWindowInPrimary->consumeMotionDown();
5405
5406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005407 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005408 ADISPLAY_ID_DEFAULT, {150, 50}))
5409 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5410 firstWindowInPrimary->assertNoEvents();
5411 secondWindowInPrimary->consumeMotionMove();
5412
5413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005414 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005415 {150, 50}))
5416 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5417 firstWindowInPrimary->assertNoEvents();
5418 secondWindowInPrimary->consumeMotionUp();
5419}
5420
5421// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5422// 'transferTouch' api.
5423TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5425 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005426 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005427 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005428 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005429 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005430 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005431
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005432 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005433 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005434
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005435 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005436 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005437
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005438 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005439 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005440
5441 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005442 mDispatcher->onWindowInfosChanged(
5443 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5444 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5445 *secondWindowInPrimary->getInfo()},
5446 {},
5447 0,
5448 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005449
5450 // Touch on second display.
5451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005452 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5453 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5455
5456 // Window should receive motion event.
5457 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5458
5459 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005460 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005461
5462 // The first window gets cancel.
5463 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5464 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5465
5466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005467 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005468 SECOND_DISPLAY_ID, {150, 50}))
5469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5470 firstWindowInPrimary->assertNoEvents();
5471 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5472
5473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005474 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5476 firstWindowInPrimary->assertNoEvents();
5477 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5478}
5479
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005480TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005481 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005482 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5483 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005484
Vishnu Nair47074b82020-08-14 11:54:47 -07005485 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005486 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005487 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005488
5489 window->consumeFocusEvent(true);
5490
Prabir Pradhan678438e2023-04-13 19:32:51 +00005491 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005492
5493 // Window should receive key down event.
5494 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005495
5496 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005497 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005498 mFakePolicy->assertUserActivityPoked();
5499}
5500
5501TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5502 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5503 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5504 "Fake Window", ADISPLAY_ID_DEFAULT);
5505
5506 window->setDisableUserActivity(true);
5507 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005508 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005509 setFocusedWindow(window);
5510
5511 window->consumeFocusEvent(true);
5512
5513 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5514
5515 // Window should receive key down event.
5516 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5517
5518 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005519 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005520 mFakePolicy->assertUserActivityNotPoked();
5521}
5522
5523TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5525 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5526 "Fake Window", ADISPLAY_ID_DEFAULT);
5527
5528 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005529 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005530 setFocusedWindow(window);
5531
5532 window->consumeFocusEvent(true);
5533
5534 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5535 mDispatcher->waitForIdle();
5536
5537 // System key is not passed down
5538 window->assertNoEvents();
5539
5540 // Should have poked user activity
5541 mFakePolicy->assertUserActivityPoked();
5542}
5543
5544TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5546 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5547 "Fake Window", ADISPLAY_ID_DEFAULT);
5548
5549 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005550 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005551 setFocusedWindow(window);
5552
5553 window->consumeFocusEvent(true);
5554
5555 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5556 mDispatcher->waitForIdle();
5557
5558 // System key is not passed down
5559 window->assertNoEvents();
5560
5561 // Should have poked user activity
5562 mFakePolicy->assertUserActivityPoked();
5563}
5564
5565TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5567 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5568 "Fake Window", ADISPLAY_ID_DEFAULT);
5569
5570 window->setDisableUserActivity(true);
5571 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005573 setFocusedWindow(window);
5574
5575 window->consumeFocusEvent(true);
5576
5577 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5578 mDispatcher->waitForIdle();
5579
5580 // System key is not passed down
5581 window->assertNoEvents();
5582
5583 // Should have poked user activity
5584 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005585}
5586
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005587TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5589 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5590 "Fake Window", ADISPLAY_ID_DEFAULT);
5591
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005592 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005593
5594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005595 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005596 ADISPLAY_ID_DEFAULT, {100, 100}))
5597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5598
5599 window->consumeMotionEvent(
5600 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5601
5602 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005603 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005604 mFakePolicy->assertUserActivityPoked();
5605}
5606
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005607TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005608 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005609 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5610 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005611
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005612 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005613
Prabir Pradhan678438e2023-04-13 19:32:51 +00005614 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005615 mDispatcher->waitForIdle();
5616
5617 window->assertNoEvents();
5618}
5619
5620// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5621TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005623 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5624 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005625
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005626 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005627
5628 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005629 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005630 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005631 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5632 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005633
5634 // Window should receive only the motion event
5635 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5636 window->assertNoEvents(); // Key event or focus event will not be received
5637}
5638
arthurhungea3f4fc2020-12-21 23:18:53 +08005639TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5640 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5641
arthurhungea3f4fc2020-12-21 23:18:53 +08005642 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005643 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5644 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005645 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005646
arthurhungea3f4fc2020-12-21 23:18:53 +08005647 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005648 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5649 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005650 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005651
5652 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005653 mDispatcher->onWindowInfosChanged(
5654 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005655
5656 PointF pointInFirst = {300, 200};
5657 PointF pointInSecond = {300, 600};
5658
5659 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005660 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5661 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5662 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005663 // Only the first window should get the down event
5664 firstWindow->consumeMotionDown();
5665 secondWindow->assertNoEvents();
5666
5667 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005668 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5669 ADISPLAY_ID_DEFAULT,
5670 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005671 // The first window gets a move and the second a down
5672 firstWindow->consumeMotionMove();
5673 secondWindow->consumeMotionDown();
5674
5675 // Send pointer cancel to the second window
5676 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005677 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005678 {pointInFirst, pointInSecond});
5679 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005680 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005681 // The first window gets move and the second gets cancel.
5682 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5683 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5684
5685 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005686 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5687 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005688 // The first window gets up and the second gets nothing.
5689 firstWindow->consumeMotionUp();
5690 secondWindow->assertNoEvents();
5691}
5692
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005693TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5695
5696 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005697 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005698 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005699 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5700 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5701 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5702
Harry Cutts33476232023-01-30 19:57:29 +00005703 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005704 window->assertNoEvents();
5705 mDispatcher->waitForIdle();
5706}
5707
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005708using InputDispatcherMonitorTest = InputDispatcherTest;
5709
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005710/**
5711 * Two entities that receive touch: A window, and a global monitor.
5712 * The touch goes to the window, and then the window disappears.
5713 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5714 * for the monitor, as well.
5715 * 1. foregroundWindow
5716 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5717 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005718TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5720 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005721 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005722
Prabir Pradhanfb549072023-10-05 19:17:36 +00005723 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005724
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005728 {100, 200}))
5729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5730
5731 // Both the foreground window and the global monitor should receive the touch down
5732 window->consumeMotionDown();
5733 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5734
5735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005736 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005737 ADISPLAY_ID_DEFAULT, {110, 200}))
5738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5739
5740 window->consumeMotionMove();
5741 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5742
5743 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005744 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005745 window->consumeMotionCancel();
5746 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5747
5748 // If more events come in, there will be no more foreground window to send them to. This will
5749 // cause a cancel for the monitor, as well.
5750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005751 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005752 ADISPLAY_ID_DEFAULT, {120, 200}))
5753 << "Injection should fail because the window was removed";
5754 window->assertNoEvents();
5755 // Global monitor now gets the cancel
5756 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5757}
5758
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005759TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005761 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5762 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005763 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005764
Prabir Pradhanfb549072023-10-05 19:17:36 +00005765 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005766
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005768 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005770 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005771 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005772}
5773
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005774TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005775 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005776
Chris Yea209fde2020-07-22 13:54:51 -07005777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005778 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5779 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005781
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005783 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005785 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005786 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005787
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005788 // Pilfer pointers from the monitor.
5789 // This should not do anything and the window should continue to receive events.
5790 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005791
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005793 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005794 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005796
5797 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5798 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005799}
5800
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005801TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005802 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005803 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5804 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005805 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005806 window->setWindowOffset(20, 40);
5807 window->setWindowTransform(0, 1, -1, 0);
5808
Prabir Pradhanfb549072023-10-05 19:17:36 +00005809 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005810
5811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005812 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5814 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5815 MotionEvent* event = monitor.consumeMotion();
5816 // Even though window has transform, gesture monitor must not.
5817 ASSERT_EQ(ui::Transform(), event->getTransform());
5818}
5819
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005820TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005822 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005823
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005824 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005826 << "Injection should fail if there is a monitor, but no touchable window";
5827 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005828}
5829
chaviw81e2bb92019-12-18 15:03:51 -08005830TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005832 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5833 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005834
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005835 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005836
5837 NotifyMotionArgs motionArgs =
5838 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5839 ADISPLAY_ID_DEFAULT);
5840
Prabir Pradhan678438e2023-04-13 19:32:51 +00005841 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005842 // Window should receive motion down event.
5843 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5844
5845 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005846 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005847 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5848 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5849 motionArgs.pointerCoords[0].getX() - 10);
5850
Prabir Pradhan678438e2023-04-13 19:32:51 +00005851 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005852 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005853 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005854}
5855
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005856/**
5857 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5858 * the device default right away. In the test scenario, we check both the default value,
5859 * and the action of enabling / disabling.
5860 */
5861TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005863 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5864 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005865 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005866
5867 // Set focused application.
5868 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005869 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005870
5871 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005872 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005873 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005874 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005875
5876 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005877 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005878 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005879 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005880
5881 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005882 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005883 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005884 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005885 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005886 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005887 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005888 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005889
5890 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005891 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005892 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005893 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005894
5895 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005896 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005897 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005898 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005899 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005900 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005901 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005902 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005903
5904 window->assertNoEvents();
5905}
5906
Gang Wange9087892020-01-07 12:17:14 -05005907TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005909 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5910 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005911
5912 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005913 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005914
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005915 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005916 setFocusedWindow(window);
5917
Harry Cutts33476232023-01-30 19:57:29 +00005918 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005919
Prabir Pradhan678438e2023-04-13 19:32:51 +00005920 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5921 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005922
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005923 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005924 ASSERT_NE(event, nullptr);
5925
5926 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5927 ASSERT_NE(verified, nullptr);
5928 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5929
5930 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5931 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5932 ASSERT_EQ(keyArgs.source, verified->source);
5933 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5934
5935 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5936
5937 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005938 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005939 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005940 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5941 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5942 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5943 ASSERT_EQ(0, verifiedKey.repeatCount);
5944}
5945
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005946TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005948 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5949 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005950
5951 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5952
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005953 ui::Transform transform;
5954 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5955
5956 gui::DisplayInfo displayInfo;
5957 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5958 displayInfo.transform = transform;
5959
Patrick Williamsd828f302023-04-28 17:52:08 -05005960 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005961
Prabir Pradhan678438e2023-04-13 19:32:51 +00005962 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005963 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5964 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005965 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005966
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005967 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005968 ASSERT_NE(event, nullptr);
5969
5970 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5971 ASSERT_NE(verified, nullptr);
5972 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5973
5974 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5975 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5976 EXPECT_EQ(motionArgs.source, verified->source);
5977 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5978
5979 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5980
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005981 const vec2 rawXY =
5982 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5983 motionArgs.pointerCoords[0].getXYValue());
5984 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5985 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005986 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005987 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005988 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005989 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5990 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5991}
5992
chaviw09c8d2d2020-08-24 15:48:26 -07005993/**
5994 * Ensure that separate calls to sign the same data are generating the same key.
5995 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5996 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5997 * tests.
5998 */
5999TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6000 KeyEvent event = getTestKeyEvent();
6001 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6002
6003 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6004 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6005 ASSERT_EQ(hmac1, hmac2);
6006}
6007
6008/**
6009 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6010 */
6011TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6012 KeyEvent event = getTestKeyEvent();
6013 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6014 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6015
6016 verifiedEvent.deviceId += 1;
6017 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6018
6019 verifiedEvent.source += 1;
6020 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6021
6022 verifiedEvent.eventTimeNanos += 1;
6023 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6024
6025 verifiedEvent.displayId += 1;
6026 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6027
6028 verifiedEvent.action += 1;
6029 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6030
6031 verifiedEvent.downTimeNanos += 1;
6032 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6033
6034 verifiedEvent.flags += 1;
6035 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6036
6037 verifiedEvent.keyCode += 1;
6038 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6039
6040 verifiedEvent.scanCode += 1;
6041 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6042
6043 verifiedEvent.metaState += 1;
6044 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6045
6046 verifiedEvent.repeatCount += 1;
6047 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6048}
6049
Vishnu Nair958da932020-08-21 17:12:37 -07006050TEST_F(InputDispatcherTest, SetFocusedWindow) {
6051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6052 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006053 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006054 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006055 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006056 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6057
6058 // Top window is also focusable but is not granted focus.
6059 windowTop->setFocusable(true);
6060 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006061 mDispatcher->onWindowInfosChanged(
6062 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006063 setFocusedWindow(windowSecond);
6064
6065 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006067 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006068
6069 // Focused window should receive event.
6070 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6071 windowTop->assertNoEvents();
6072}
6073
6074TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6076 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006077 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006078 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6079
6080 window->setFocusable(true);
6081 // Release channel for window is no longer valid.
6082 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006083 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006084 setFocusedWindow(window);
6085
6086 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006087 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006088
6089 // window channel is invalid, so it should not receive any input event.
6090 window->assertNoEvents();
6091}
6092
6093TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6095 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006096 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006097 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006098 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6099
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006100 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006101 setFocusedWindow(window);
6102
6103 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006104 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006105
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006106 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006107 window->assertNoEvents();
6108}
6109
6110TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6112 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006113 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006114 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006115 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006116 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6117
6118 windowTop->setFocusable(true);
6119 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006120 mDispatcher->onWindowInfosChanged(
6121 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006122 setFocusedWindow(windowTop);
6123 windowTop->consumeFocusEvent(true);
6124
Chavi Weingarten847e8512023-03-29 00:26:09 +00006125 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006126 mDispatcher->onWindowInfosChanged(
6127 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006128 windowSecond->consumeFocusEvent(true);
6129 windowTop->consumeFocusEvent(false);
6130
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006132 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006133
6134 // Focused window should receive event.
6135 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6136}
6137
Chavi Weingarten847e8512023-03-29 00:26:09 +00006138TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006139 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6140 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006141 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006142 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006143 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006144 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6145
6146 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006147 windowSecond->setFocusable(false);
6148 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006149 mDispatcher->onWindowInfosChanged(
6150 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006151 setFocusedWindow(windowTop);
6152 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006153
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006155 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006156
6157 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006158 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006159 windowSecond->assertNoEvents();
6160}
6161
6162TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6163 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6164 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006165 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006166 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006167 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6168 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006169 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6170
6171 window->setFocusable(true);
6172 previousFocusedWindow->setFocusable(true);
6173 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006174 mDispatcher->onWindowInfosChanged(
6175 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006176 setFocusedWindow(previousFocusedWindow);
6177 previousFocusedWindow->consumeFocusEvent(true);
6178
6179 // Requesting focus on invisible window takes focus from currently focused window.
6180 setFocusedWindow(window);
6181 previousFocusedWindow->consumeFocusEvent(false);
6182
6183 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006185 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6186 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006187
6188 // Window does not get focus event or key down.
6189 window->assertNoEvents();
6190
6191 // Window becomes visible.
6192 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006194
6195 // Window receives focus event.
6196 window->consumeFocusEvent(true);
6197 // Focused window receives key down.
6198 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6199}
6200
Vishnu Nair599f1412021-06-21 10:39:58 -07006201TEST_F(InputDispatcherTest, DisplayRemoved) {
6202 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6203 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006204 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006205 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6206
6207 // window is granted focus.
6208 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006209 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006210 setFocusedWindow(window);
6211 window->consumeFocusEvent(true);
6212
6213 // When a display is removed window loses focus.
6214 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6215 window->consumeFocusEvent(false);
6216}
6217
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006218/**
6219 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6220 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6221 * of the 'slipperyEnterWindow'.
6222 *
6223 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6224 * a way so that the touched location is no longer covered by the top window.
6225 *
6226 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6227 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6228 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6229 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6230 * with ACTION_DOWN).
6231 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6232 * window moved itself away from the touched location and had Flag::SLIPPERY.
6233 *
6234 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6235 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6236 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6237 *
6238 * In this test, we ensure that the event received by the bottom window has
6239 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6240 */
6241TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006242 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006243 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006244
6245 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6246 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6247
6248 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006249 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006250 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006251 // Make sure this one overlaps the bottom window
6252 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6253 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6254 // one. Windows with the same owner are not considered to be occluding each other.
6255 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6256
6257 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006258 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006259 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6260
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006261 mDispatcher->onWindowInfosChanged(
6262 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006263
6264 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6266 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6267 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006268 slipperyExitWindow->consumeMotionDown();
6269 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006270 mDispatcher->onWindowInfosChanged(
6271 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006272
Prabir Pradhan678438e2023-04-13 19:32:51 +00006273 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6274 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6275 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006276
6277 slipperyExitWindow->consumeMotionCancel();
6278
6279 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6280 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6281}
6282
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006283/**
6284 * Two windows, one on the left and another on the right. The left window is slippery. The right
6285 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6286 * touch moves from the left window into the right window, the gesture should continue to go to the
6287 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6288 * reproduces a crash.
6289 */
6290TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6291 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6292
6293 sp<FakeWindowHandle> leftSlipperyWindow =
6294 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6295 leftSlipperyWindow->setSlippery(true);
6296 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6297
6298 sp<FakeWindowHandle> rightDropTouchesWindow =
6299 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6300 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6301 rightDropTouchesWindow->setDropInput(true);
6302
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006303 mDispatcher->onWindowInfosChanged(
6304 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006305
6306 // Start touch in the left window
6307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6308 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6309 .build());
6310 leftSlipperyWindow->consumeMotionDown();
6311
6312 // And move it into the right window
6313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6314 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6315 .build());
6316
6317 // Since the right window isn't eligible to receive input, touch does not slip.
6318 // The left window continues to receive the gesture.
6319 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6320 rightDropTouchesWindow->assertNoEvents();
6321}
6322
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006323/**
6324 * A single window is on screen first. Touch is injected into that window. Next, a second window
6325 * appears. Since the first window is slippery, touch will move from the first window to the second.
6326 */
6327TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6329 sp<FakeWindowHandle> originalWindow =
6330 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6331 originalWindow->setFrame(Rect(0, 0, 200, 200));
6332 originalWindow->setSlippery(true);
6333
6334 sp<FakeWindowHandle> appearingWindow =
6335 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6336 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6337
6338 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6339
6340 // Touch down on the original window
6341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6342 injectMotionEvent(*mDispatcher,
6343 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6344 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6345 .build()));
6346 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6347
6348 // Now, a new window appears. This could be, for example, a notification shade that appears
6349 // after user starts to drag down on the launcher window.
6350 mDispatcher->onWindowInfosChanged(
6351 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6353 injectMotionEvent(*mDispatcher,
6354 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6355 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6356 .build()));
6357 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6358 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6360 injectMotionEvent(*mDispatcher,
6361 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6362 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6363 .build()));
6364 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6365
6366 originalWindow->assertNoEvents();
6367 appearingWindow->assertNoEvents();
6368}
6369
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006370TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006371 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6373
6374 sp<FakeWindowHandle> leftWindow =
6375 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6376 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006377 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006378
6379 sp<FakeWindowHandle> rightSpy =
6380 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6381 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006382 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006383 rightSpy->setSpy(true);
6384 rightSpy->setTrustedOverlay(true);
6385
6386 sp<FakeWindowHandle> rightWindow =
6387 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6388 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006389 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006390
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006391 mDispatcher->onWindowInfosChanged(
6392 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006393
6394 // Touch in the left window
6395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6396 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6397 .build());
6398 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6399 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006400 ASSERT_NO_FATAL_FAILURE(
6401 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006402
6403 // Touch another finger over the right windows
6404 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6405 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6406 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6407 .build());
6408 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6409 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6410 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6411 mDispatcher->waitForIdle();
6412 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006413 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6414 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006415
6416 // Release finger over left window. The UP actions are not treated as device interaction.
6417 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6418 // is part of the UP action, we do not treat this as device interaction.
6419 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6420 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6421 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6422 .build());
6423 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6424 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6425 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6426 mDispatcher->waitForIdle();
6427 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6428
6429 // Move remaining finger
6430 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6431 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6432 .build());
6433 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6434 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6435 mDispatcher->waitForIdle();
6436 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006437 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006438
6439 // Release all fingers
6440 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6441 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6442 .build());
6443 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6444 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6445 mDispatcher->waitForIdle();
6446 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6447}
6448
6449TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6451
6452 sp<FakeWindowHandle> window =
6453 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6454 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006455 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006456
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006457 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006458 setFocusedWindow(window);
6459 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6460
6461 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6462 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6463 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006464 ASSERT_NO_FATAL_FAILURE(
6465 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006466
6467 // The UP actions are not treated as device interaction.
6468 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6469 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6470 mDispatcher->waitForIdle();
6471 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6472}
6473
Garfield Tan1c7bc862020-01-28 13:24:04 -08006474class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6475protected:
6476 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6477 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6478
Chris Yea209fde2020-07-22 13:54:51 -07006479 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006480 sp<FakeWindowHandle> mWindow;
6481
6482 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006483 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006484 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006485 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006486 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006487 ASSERT_EQ(OK, mDispatcher->start());
6488
6489 setUpWindow();
6490 }
6491
6492 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006493 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006494 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006495
Vishnu Nair47074b82020-08-14 11:54:47 -07006496 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006497 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006498 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006499 mWindow->consumeFocusEvent(true);
6500 }
6501
Chris Ye2ad95392020-09-01 13:44:44 -07006502 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006503 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006504 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006505 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006506 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006507
6508 // Window should receive key down event.
6509 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6510 }
6511
6512 void expectKeyRepeatOnce(int32_t repeatCount) {
6513 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006514 mWindow->consumeKeyEvent(
6515 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006516 }
6517
Chris Ye2ad95392020-09-01 13:44:44 -07006518 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006519 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006520 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006521 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006522 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006523
6524 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006525 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006526 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006527 }
6528};
6529
6530TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
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 }
6535}
6536
6537TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006538 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006539 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6540 expectKeyRepeatOnce(repeatCount);
6541 }
Harry Cutts33476232023-01-30 19:57:29 +00006542 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006543 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006544 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6545 expectKeyRepeatOnce(repeatCount);
6546 }
6547}
6548
6549TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006550 sendAndConsumeKeyDown(/*deviceId=*/1);
6551 expectKeyRepeatOnce(/*repeatCount=*/1);
6552 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006553 mWindow->assertNoEvents();
6554}
6555
6556TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006557 sendAndConsumeKeyDown(/*deviceId=*/1);
6558 expectKeyRepeatOnce(/*repeatCount=*/1);
6559 sendAndConsumeKeyDown(/*deviceId=*/2);
6560 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006561 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006562 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006563 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006564 expectKeyRepeatOnce(/*repeatCount=*/2);
6565 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006566 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006567 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006568 mWindow->assertNoEvents();
6569}
6570
6571TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006572 sendAndConsumeKeyDown(/*deviceId=*/1);
6573 expectKeyRepeatOnce(/*repeatCount=*/1);
6574 sendAndConsumeKeyDown(/*deviceId=*/2);
6575 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006576 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006577 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006578 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006579 mWindow->assertNoEvents();
6580}
6581
liushenxiang42232912021-05-21 20:24:09 +08006582TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6583 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006584 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006585 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006586 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6587 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6588 mWindow->assertNoEvents();
6589}
6590
Garfield Tan1c7bc862020-01-28 13:24:04 -08006591TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006592 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006593 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006594 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006595 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006596 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6597 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6598 IdGenerator::getSource(repeatEvent->getId()));
6599 }
6600}
6601
6602TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006603 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006604 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006605
6606 std::unordered_set<int32_t> idSet;
6607 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006608 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006609 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6610 int32_t id = repeatEvent->getId();
6611 EXPECT_EQ(idSet.end(), idSet.find(id));
6612 idSet.insert(id);
6613 }
6614}
6615
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006616/* Test InputDispatcher for MultiDisplay */
6617class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6618public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006619 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006620 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006621
Chris Yea209fde2020-07-22 13:54:51 -07006622 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006623 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006624 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006625
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006626 // Set focus window for primary display, but focused display would be second one.
6627 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006628 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006629 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6630
Vishnu Nair958da932020-08-21 17:12:37 -07006631 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006632 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006633
Chris Yea209fde2020-07-22 13:54:51 -07006634 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006635 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006636 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006637 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006638 // Set focus display to second one.
6639 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6640 // Set focus window for second display.
6641 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006642 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006643 mDispatcher->onWindowInfosChanged(
6644 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006645 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006646 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006647 }
6648
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006649 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006650 InputDispatcherTest::TearDown();
6651
Chris Yea209fde2020-07-22 13:54:51 -07006652 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006653 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006654 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006655 windowInSecondary.clear();
6656 }
6657
6658protected:
Chris Yea209fde2020-07-22 13:54:51 -07006659 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006660 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006661 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006662 sp<FakeWindowHandle> windowInSecondary;
6663};
6664
6665TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6666 // Test touch down on primary 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, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006670 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006671 windowInSecondary->assertNoEvents();
6672
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006673 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006675 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006677 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006678 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006679}
6680
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006681TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006682 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006684 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006685 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006686 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006687 windowInSecondary->assertNoEvents();
6688
6689 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006691 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006692 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006693 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006694
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006695 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006696 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006697
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006698 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006699 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006700 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006701
6702 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006703 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006704 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006705 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006706 windowInSecondary->assertNoEvents();
6707}
6708
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006709// Test per-display input monitors for motion event.
6710TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006711 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006712 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006713 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006714 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006715
6716 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006718 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006720 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006721 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006722 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006723 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006724
6725 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006728 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006729 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006730 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006731 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006732 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006733
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006734 // Lift up the touch from the second display
6735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006736 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6738 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6739 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6740
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006741 // Test inject a non-pointer motion event.
6742 // If specific a display, it will dispatch to the focused window of particular display,
6743 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006745 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006747 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006748 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006749 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006750 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006751}
6752
6753// Test per-display input monitors for key event.
6754TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006755 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006756 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006757 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006758 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006759 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006760
6761 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006763 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006764 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006765 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006766 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006767 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006768}
6769
Vishnu Nair958da932020-08-21 17:12:37 -07006770TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6771 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006772 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006773 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006774 mDispatcher->onWindowInfosChanged(
6775 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6776 *windowInSecondary->getInfo()},
6777 {},
6778 0,
6779 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006780 setFocusedWindow(secondWindowInPrimary);
6781 windowInPrimary->consumeFocusEvent(false);
6782 secondWindowInPrimary->consumeFocusEvent(true);
6783
6784 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6786 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006787 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006788 windowInPrimary->assertNoEvents();
6789 windowInSecondary->assertNoEvents();
6790 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6791}
6792
Arthur Hungdfd528e2021-12-08 13:23:04 +00006793TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6794 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006795 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006796 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006797 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006798
6799 // Test touch down on primary display.
6800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6803 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6804 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6805
6806 // Test touch down on second display.
6807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006808 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6810 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6811 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6812
6813 // Trigger cancel touch.
6814 mDispatcher->cancelCurrentTouch();
6815 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6816 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6817 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6818 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6819
6820 // Test inject a move motion event, no window/monitor should receive the event.
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 ADISPLAY_ID_DEFAULT, {110, 200}))
6824 << "Inject motion event should return InputEventInjectionResult::FAILED";
6825 windowInPrimary->assertNoEvents();
6826 monitorInPrimary.assertNoEvents();
6827
6828 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006829 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006830 SECOND_DISPLAY_ID, {110, 200}))
6831 << "Inject motion event should return InputEventInjectionResult::FAILED";
6832 windowInSecondary->assertNoEvents();
6833 monitorInSecondary.assertNoEvents();
6834}
6835
Jackal Guof9696682018-10-05 12:23:23 +08006836class InputFilterTest : public InputDispatcherTest {
6837protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006838 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6839 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006840 NotifyMotionArgs motionArgs;
6841
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006842 motionArgs =
6843 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006844 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006845 motionArgs =
6846 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006847 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006848 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006849 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006850 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006851 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006852 } else {
6853 mFakePolicy->assertFilterInputEventWasNotCalled();
6854 }
6855 }
6856
6857 void testNotifyKey(bool expectToBeFiltered) {
6858 NotifyKeyArgs keyArgs;
6859
6860 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006861 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006862 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006863 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006864 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006865
6866 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006867 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006868 } else {
6869 mFakePolicy->assertFilterInputEventWasNotCalled();
6870 }
6871 }
6872};
6873
6874// Test InputFilter for MotionEvent
6875TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6876 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006877 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6878 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006879
6880 // Enable InputFilter
6881 mDispatcher->setInputFilterEnabled(true);
6882 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006883 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6884 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006885
6886 // Disable InputFilter
6887 mDispatcher->setInputFilterEnabled(false);
6888 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006889 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6890 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006891}
6892
6893// Test InputFilter for KeyEvent
6894TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6895 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006896 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006897
6898 // Enable InputFilter
6899 mDispatcher->setInputFilterEnabled(true);
6900 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006901 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006902
6903 // Disable InputFilter
6904 mDispatcher->setInputFilterEnabled(false);
6905 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006906 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006907}
6908
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006909// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6910// logical display coordinate space.
6911TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6912 ui::Transform firstDisplayTransform;
6913 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6914 ui::Transform secondDisplayTransform;
6915 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6916
6917 std::vector<gui::DisplayInfo> displayInfos(2);
6918 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6919 displayInfos[0].transform = firstDisplayTransform;
6920 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6921 displayInfos[1].transform = secondDisplayTransform;
6922
Patrick Williamsd828f302023-04-28 17:52:08 -05006923 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006924
6925 // Enable InputFilter
6926 mDispatcher->setInputFilterEnabled(true);
6927
6928 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006929 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6930 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006931}
6932
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006933class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6934protected:
6935 virtual void SetUp() override {
6936 InputDispatcherTest::SetUp();
6937
6938 /**
6939 * We don't need to enable input filter to test the injected event policy, but we enabled it
6940 * here to make the tests more realistic, since this policy only matters when inputfilter is
6941 * on.
6942 */
6943 mDispatcher->setInputFilterEnabled(true);
6944
6945 std::shared_ptr<InputApplicationHandle> application =
6946 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006947 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6948 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006949
6950 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6951 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006952 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006953 setFocusedWindow(mWindow);
6954 mWindow->consumeFocusEvent(true);
6955 }
6956
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006957 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6958 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006959 KeyEvent event;
6960
6961 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6962 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6963 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006964 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006965 const int32_t additionalPolicyFlags =
6966 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006968 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006969 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006970 policyFlags | additionalPolicyFlags));
6971
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006972 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006973 }
6974
6975 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6976 int32_t flags) {
6977 MotionEvent event;
6978 PointerProperties pointerProperties[1];
6979 PointerCoords pointerCoords[1];
6980 pointerProperties[0].clear();
6981 pointerProperties[0].id = 0;
6982 pointerCoords[0].clear();
6983 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6984 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6985
6986 ui::Transform identityTransform;
6987 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6988 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6989 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6990 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6991 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006992 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006993 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006994 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006995
6996 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006998 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006999 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007000 policyFlags | additionalPolicyFlags));
7001
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007002 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007003 }
7004
7005private:
7006 sp<FakeWindowHandle> mWindow;
7007};
7008
7009TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007010 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7011 // filter. Without it, the event will no different from a regularly injected event, and the
7012 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007013 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7014 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007015}
7016
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007017TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007018 testInjectedKey(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 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7021}
7022
7023TEST_F(InputFilterInjectionPolicyTest,
7024 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7025 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007026 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007027 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007028}
7029
7030TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007031 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7032 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007033}
7034
chaviwfd6d3512019-03-25 13:23:49 -07007035class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007036 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007037 InputDispatcherTest::SetUp();
7038
Chris Yea209fde2020-07-22 13:54:51 -07007039 std::shared_ptr<FakeApplicationHandle> application =
7040 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007041 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007042 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007043 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007044
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007045 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007046 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007047 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007048
7049 // Set focused application.
7050 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007051 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007052
7053 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007054 mDispatcher->onWindowInfosChanged(
7055 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007056 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007057 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007058 }
7059
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007060 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007061 InputDispatcherTest::TearDown();
7062
7063 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007064 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007065 }
7066
7067protected:
7068 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007069 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007070 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007071};
7072
7073// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7074// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7075// the onPointerDownOutsideFocus callback.
7076TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007078 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007079 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007081 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007082
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007083 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007084 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7085}
7086
7087// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7088// DOWN on the window that doesn't have focus. Ensure no window received the
7089// onPointerDownOutsideFocus callback.
7090TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007092 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7093 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007095 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007096
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007097 ASSERT_TRUE(mDispatcher->waitForIdle());
7098 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007099}
7100
7101// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7102// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7103TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007105 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007106 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007107 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007108
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007109 ASSERT_TRUE(mDispatcher->waitForIdle());
7110 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007111}
7112
7113// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7114// DOWN on the window that already has focus. Ensure no window received the
7115// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007116TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007119 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007121 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007122
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007123 ASSERT_TRUE(mDispatcher->waitForIdle());
7124 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007125}
7126
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007127// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7128// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7129TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7130 const MotionEvent event =
7131 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7132 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007133 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007134 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7135 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7138 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7139
7140 ASSERT_TRUE(mDispatcher->waitForIdle());
7141 mFakePolicy->assertOnPointerDownWasNotCalled();
7142 // Ensure that the unfocused window did not receive any FOCUS events.
7143 mUnfocusedWindow->assertNoEvents();
7144}
7145
chaviwaf87b3e2019-10-01 16:59:28 -07007146// These tests ensures we can send touch events to a single client when there are multiple input
7147// windows that point to the same client token.
7148class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7149 virtual void SetUp() override {
7150 InputDispatcherTest::SetUp();
7151
Chris Yea209fde2020-07-22 13:54:51 -07007152 std::shared_ptr<FakeApplicationHandle> application =
7153 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007154 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7155 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007156 mWindow1->setFrame(Rect(0, 0, 100, 100));
7157
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007158 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7159 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007160 mWindow2->setFrame(Rect(100, 100, 200, 200));
7161
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007162 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007163 }
7164
7165protected:
7166 sp<FakeWindowHandle> mWindow1;
7167 sp<FakeWindowHandle> mWindow2;
7168
7169 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007170 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007171 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7172 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007173 }
7174
7175 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7176 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007177 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007178 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007179
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007180 ASSERT_NE(nullptr, motionEvent)
7181 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007182
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007183 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007184 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007185
7186 for (size_t i = 0; i < points.size(); i++) {
7187 float expectedX = points[i].x;
7188 float expectedY = points[i].y;
7189
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007190 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007191 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007192 << ", got " << motionEvent->getX(i);
7193 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007194 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007195 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007196 }
7197 }
chaviw9eaa22c2020-07-01 16:21:27 -07007198
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007199 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007200 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007201 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7202 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007203
7204 // Always consume from window1 since it's the window that has the InputReceiver
7205 consumeMotionEvent(mWindow1, action, expectedPoints);
7206 }
chaviwaf87b3e2019-10-01 16:59:28 -07007207};
7208
7209TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7210 // Touch Window 1
7211 PointF touchedPoint = {10, 10};
7212 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007213 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007214
7215 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007216 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007217
7218 // Touch Window 2
7219 touchedPoint = {150, 150};
7220 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007221 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007222}
7223
chaviw9eaa22c2020-07-01 16:21:27 -07007224TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7225 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007226 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007227 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007228
7229 // Touch Window 1
7230 PointF touchedPoint = {10, 10};
7231 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007232 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007233 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007234 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007235
7236 // Touch Window 2
7237 touchedPoint = {150, 150};
7238 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007239 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7240 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007241
chaviw9eaa22c2020-07-01 16:21:27 -07007242 // Update the transform so rotation is set
7243 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007244 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007245 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7246 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007247}
7248
chaviw9eaa22c2020-07-01 16:21:27 -07007249TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007250 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007251 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007252
7253 // Touch Window 1
7254 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7255 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007256 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007257
7258 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007259 touchedPoints.push_back(PointF{150, 150});
7260 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007261 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007262
chaviw9eaa22c2020-07-01 16:21:27 -07007263 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007264 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007265 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007266
chaviw9eaa22c2020-07-01 16:21:27 -07007267 // Update the transform so rotation is set for Window 2
7268 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007269 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007270 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007271 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007272}
7273
chaviw9eaa22c2020-07-01 16:21:27 -07007274TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007275 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007276 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007277
7278 // Touch Window 1
7279 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7280 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007281 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007282
7283 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007284 touchedPoints.push_back(PointF{150, 150});
7285 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007286
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007287 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007288
7289 // Move both windows
7290 touchedPoints = {{20, 20}, {175, 175}};
7291 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7292 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7293
chaviw9eaa22c2020-07-01 16:21:27 -07007294 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007295
chaviw9eaa22c2020-07-01 16:21:27 -07007296 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007297 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007298 expectedPoints.pop_back();
7299
7300 // Touch Window 2
7301 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007302 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007303 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007304 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007305
7306 // Move both windows
7307 touchedPoints = {{20, 20}, {175, 175}};
7308 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7309 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7310
7311 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007312}
7313
7314TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7315 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007316 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007317
7318 // Touch Window 1
7319 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7320 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007321 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007322
7323 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007324 touchedPoints.push_back(PointF{150, 150});
7325 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007326
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007327 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007328
7329 // Move both windows
7330 touchedPoints = {{20, 20}, {175, 175}};
7331 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7332 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7333
chaviw9eaa22c2020-07-01 16:21:27 -07007334 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007335}
7336
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007337/**
7338 * When one of the windows is slippery, the touch should not slip into the other window with the
7339 * same input channel.
7340 */
7341TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7342 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007343 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007344
7345 // Touch down in window 1
7346 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7347 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7348 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7349
7350 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7351 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7352 // getting generated.
7353 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7354 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7355
7356 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7357}
7358
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007359/**
7360 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7361 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7362 * that the pointer is hovering over may have a different transform.
7363 */
7364TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007365 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007366
7367 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7369 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7370 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007371 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7372 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007373 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7375 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7376 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007377 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7378 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7379 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7380}
7381
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007382class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7383 virtual void SetUp() override {
7384 InputDispatcherTest::SetUp();
7385
Chris Yea209fde2020-07-22 13:54:51 -07007386 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007387 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007388 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7389 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007390 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007391 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007392 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007393
7394 // Set focused application.
7395 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7396
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007397 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007398 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007399 mWindow->consumeFocusEvent(true);
7400 }
7401
7402 virtual void TearDown() override {
7403 InputDispatcherTest::TearDown();
7404 mWindow.clear();
7405 }
7406
7407protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007408 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007409 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007410 sp<FakeWindowHandle> mWindow;
7411 static constexpr PointF WINDOW_LOCATION = {20, 20};
7412
7413 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007416 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007418 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007419 WINDOW_LOCATION));
7420 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007421
7422 sp<FakeWindowHandle> addSpyWindow() {
7423 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007424 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007425 spy->setTrustedOverlay(true);
7426 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007427 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007428 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007429 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007430 return spy;
7431 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007432};
7433
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434// Send a tap and respond, which should not cause an ANR.
7435TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7436 tapOnWindow();
7437 mWindow->consumeMotionDown();
7438 mWindow->consumeMotionUp();
7439 ASSERT_TRUE(mDispatcher->waitForIdle());
7440 mFakePolicy->assertNotifyAnrWasNotCalled();
7441}
7442
7443// Send a regular key and respond, which should not cause an ANR.
7444TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007446 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7447 ASSERT_TRUE(mDispatcher->waitForIdle());
7448 mFakePolicy->assertNotifyAnrWasNotCalled();
7449}
7450
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007451TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7452 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007453 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007454 mWindow->consumeFocusEvent(false);
7455
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007456 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007457 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7458 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007459 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007461 // Key will not go to window because we have no focused window.
7462 // The 'no focused window' ANR timer should start instead.
7463
7464 // Now, the focused application goes away.
7465 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7466 // The key should get dropped and there should be no ANR.
7467
7468 ASSERT_TRUE(mDispatcher->waitForIdle());
7469 mFakePolicy->assertNotifyAnrWasNotCalled();
7470}
7471
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007472// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007473// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7474// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007475TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007477 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007478 WINDOW_LOCATION));
7479
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007480 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7481 ASSERT_TRUE(sequenceNum);
7482 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007483 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007484
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007485 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007486 mWindow->consumeMotionEvent(
7487 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007488 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007489 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007490}
7491
7492// Send a key to the app and have the app not respond right away.
7493TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7494 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007496 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7497 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007498 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007499 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007500 ASSERT_TRUE(mDispatcher->waitForIdle());
7501}
7502
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007503// We have a focused application, but no focused window
7504TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007505 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007506 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007507 mWindow->consumeFocusEvent(false);
7508
7509 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007511 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007512 WINDOW_LOCATION));
7513 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7514 mDispatcher->waitForIdle();
7515 mFakePolicy->assertNotifyAnrWasNotCalled();
7516
7517 // Once a focused event arrives, we get an ANR for this application
7518 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7519 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007520 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007521 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007522 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007523 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007524 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007525 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007526 ASSERT_TRUE(mDispatcher->waitForIdle());
7527}
7528
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007529/**
7530 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7531 * there will not be an ANR.
7532 */
7533TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7534 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007535 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007536 mWindow->consumeFocusEvent(false);
7537
7538 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007539 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7540 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007541 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7542 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7543
7544 // Define a valid key down event that is stale (too old).
7545 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007546 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007547 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007548
7549 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7550
7551 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007552 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007553 InputEventInjectionSync::WAIT_FOR_RESULT,
7554 INJECT_EVENT_TIMEOUT, policyFlags);
7555 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7556 << "Injection should fail because the event is stale";
7557
7558 ASSERT_TRUE(mDispatcher->waitForIdle());
7559 mFakePolicy->assertNotifyAnrWasNotCalled();
7560 mWindow->assertNoEvents();
7561}
7562
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007563// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007564// Make sure that we don't notify policy twice about the same ANR.
7565TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007566 const std::chrono::duration appTimeout = 400ms;
7567 mApplication->setDispatchingTimeout(appTimeout);
7568 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7569
Vishnu Nair47074b82020-08-14 11:54:47 -07007570 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007571 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007572 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007573
7574 // Once a focused event arrives, we get an ANR for this application
7575 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7576 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007577 const std::chrono::duration eventInjectionTimeout = 100ms;
7578 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007579 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007580 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007581 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7582 /*allowKeyRepeat=*/false);
7583 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7584 << "result=" << ftl::enum_string(result);
7585 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7586 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7587 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7588 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007589
Vishnu Naire4df8752022-09-08 09:17:55 -07007590 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007591 // ANR should not be raised again. It is up to policy to do that if it desires.
7592 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007593
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007594 // If we now get a focused window, the ANR should stop, but the policy handles that via
7595 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007596 ASSERT_TRUE(mDispatcher->waitForIdle());
7597}
7598
7599// We have a focused application, but no focused window
7600TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007601 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007602 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007603 mWindow->consumeFocusEvent(false);
7604
7605 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007606 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007607
Vishnu Naire4df8752022-09-08 09:17:55 -07007608 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7609 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007610
7611 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007612 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007613 ASSERT_TRUE(mDispatcher->waitForIdle());
7614 mWindow->assertNoEvents();
7615}
7616
7617/**
7618 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7619 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7620 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7621 * the ANR mechanism should still work.
7622 *
7623 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7624 * DOWN event, while not responding on the second one.
7625 */
7626TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7627 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007628 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007629 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7630 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7631 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007632 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007633
7634 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007635 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007636 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7637 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7638 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007640
7641 // We have now sent down and up. Let's consume first event and then ANR on the second.
7642 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7643 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007644 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007645}
7646
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007647// A spy window can receive an ANR
7648TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7649 sp<FakeWindowHandle> spy = addSpyWindow();
7650
7651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007652 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007653 WINDOW_LOCATION));
7654 mWindow->consumeMotionDown();
7655
7656 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7657 ASSERT_TRUE(sequenceNum);
7658 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007659 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007660
7661 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007662 spy->consumeMotionEvent(
7663 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007664 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007665 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007666}
7667
7668// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007669// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007670TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7671 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007672
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007674 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007675 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007677
7678 // Stuck on the ACTION_UP
7679 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007680 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007681
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007682 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007683 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007684 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7685 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007686
7687 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7688 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007689 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007690 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007691 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007692}
7693
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007694// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007695// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007696TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7697 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007698
7699 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007700 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7701 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007702
7703 mWindow->consumeMotionDown();
7704 // Stuck on the ACTION_UP
7705 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007706 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007707
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007708 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007709 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007710 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7711 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007712
7713 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7714 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007715 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007716 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007717 spy->assertNoEvents();
7718}
7719
7720TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007721 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007722
Prabir Pradhanfb549072023-10-05 19:17:36 +00007723 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007724
7725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007726 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007727 WINDOW_LOCATION));
7728
7729 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7730 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7731 ASSERT_TRUE(consumeSeq);
7732
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007733 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7734 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007735
7736 monitor.finishEvent(*consumeSeq);
7737 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7738
7739 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007740 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007741}
7742
7743// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7744// process events, you don't get an anr. When the window later becomes unresponsive again, you
7745// get an ANR again.
7746// 1. tap -> block on ACTION_UP -> receive ANR
7747// 2. consume all pending events (= queue becomes healthy again)
7748// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7749TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7750 tapOnWindow();
7751
7752 mWindow->consumeMotionDown();
7753 // Block on ACTION_UP
7754 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007755 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007756 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7757 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007758 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007759 mWindow->assertNoEvents();
7760
7761 tapOnWindow();
7762 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007763 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007764 mWindow->consumeMotionUp();
7765
7766 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007767 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007768 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007769 mWindow->assertNoEvents();
7770}
7771
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007772// If a connection remains unresponsive for a while, make sure policy is only notified once about
7773// it.
7774TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007776 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007777 WINDOW_LOCATION));
7778
7779 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007780 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007781 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007782 // 'notifyConnectionUnresponsive' should only be called once per connection
7783 mFakePolicy->assertNotifyAnrWasNotCalled();
7784 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007785 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007786 mWindow->consumeMotionEvent(
7787 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007788 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007789 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007790 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007791 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007792}
7793
7794/**
7795 * 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 -07007796 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007797 *
7798 * Warning!!!
7799 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7800 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007801 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007802 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7803 *
7804 * If that value changes, this test should also change.
7805 */
7806TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7807 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007808 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007809
7810 tapOnWindow();
7811 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7812 ASSERT_TRUE(downSequenceNum);
7813 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7814 ASSERT_TRUE(upSequenceNum);
7815 // Don't finish the events yet, and send a key
7816 // Injection will "succeed" because we will eventually give up and send the key to the focused
7817 // window even if motions are still being processed. But because the injection timeout is short,
7818 // we will receive INJECTION_TIMED_OUT as the result.
7819
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007820 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007821 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7822 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007823 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007824 // Key will not be sent to the window, yet, because the window is still processing events
7825 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007826 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7827 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7828 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7829 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007830
7831 std::this_thread::sleep_for(500ms);
7832 // if we wait long enough though, dispatcher will give up, and still send the key
7833 // to the focused window, even though we have not yet finished the motion event
7834 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7835 mWindow->finishEvent(*downSequenceNum);
7836 mWindow->finishEvent(*upSequenceNum);
7837}
7838
7839/**
7840 * If a window is processing a motion event, and then a key event comes in, the key event should
7841 * not go to the focused window until the motion is processed.
7842 * If then a new motion comes in, then the pending key event should be going to the currently
7843 * focused window right away.
7844 */
7845TEST_F(InputDispatcherSingleWindowAnr,
7846 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7847 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007848 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007849
7850 tapOnWindow();
7851 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7852 ASSERT_TRUE(downSequenceNum);
7853 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7854 ASSERT_TRUE(upSequenceNum);
7855 // Don't finish the events yet, and send a key
7856 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007858 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7859 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007860 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007861 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7862 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7863 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7864 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007865
7866 // Now tap down again. It should cause the pending key to go to the focused window right away.
7867 tapOnWindow();
7868 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7869 // the other events yet. We can finish events in any order.
7870 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7871 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7872 mWindow->consumeMotionDown();
7873 mWindow->consumeMotionUp();
7874 mWindow->assertNoEvents();
7875}
7876
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007877/**
7878 * Send an event to the app and have the app not respond right away.
7879 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7880 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7881 * At some point, the window becomes responsive again.
7882 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7883 */
7884TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7886 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7887 .build());
7888
7889 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7890 ASSERT_TRUE(sequenceNum);
7891 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7892 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7893
7894 mWindow->finishEvent(*sequenceNum);
7895 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7896 ASSERT_TRUE(mDispatcher->waitForIdle());
7897 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7898
7899 // Now that the window is responsive, let's continue the gesture.
7900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7901 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7902 .build());
7903
7904 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7905 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7906 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7907 .build());
7908
7909 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7910 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7911 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7912 .build());
7913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7914 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7915 .build());
7916 // We already canceled this pointer, so the window shouldn't get any new events.
7917 mWindow->assertNoEvents();
7918
7919 // Start another one.
7920 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7921 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7922 .build());
7923 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7924}
7925
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007926class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7927 virtual void SetUp() override {
7928 InputDispatcherTest::SetUp();
7929
Chris Yea209fde2020-07-22 13:54:51 -07007930 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007931 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007932 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7933 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007934 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007935 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007936 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007937
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007938 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7939 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007940 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007941 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942
7943 // Set focused application.
7944 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007945 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007946
7947 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007948 mDispatcher->onWindowInfosChanged(
7949 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007950 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007951 mFocusedWindow->consumeFocusEvent(true);
7952 }
7953
7954 virtual void TearDown() override {
7955 InputDispatcherTest::TearDown();
7956
7957 mUnfocusedWindow.clear();
7958 mFocusedWindow.clear();
7959 }
7960
7961protected:
Chris Yea209fde2020-07-22 13:54:51 -07007962 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007963 sp<FakeWindowHandle> mUnfocusedWindow;
7964 sp<FakeWindowHandle> mFocusedWindow;
7965 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7966 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7967 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7968
7969 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7970
7971 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7972
7973private:
7974 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007976 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007977 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007979 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007980 location));
7981 }
7982};
7983
7984// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7985// should be ANR'd first.
7986TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07007988 injectMotionEvent(*mDispatcher,
7989 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7990 AINPUT_SOURCE_TOUCHSCREEN)
7991 .pointer(PointerBuilder(0, ToolType::FINGER)
7992 .x(FOCUSED_WINDOW_LOCATION.x)
7993 .y(FOCUSED_WINDOW_LOCATION.y))
7994 .build()));
7995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7996 injectMotionEvent(*mDispatcher,
7997 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
7998 AINPUT_SOURCE_TOUCHSCREEN)
7999 .pointer(PointerBuilder(0, ToolType::FINGER)
8000 .x(FOCUSED_WINDOW_LOCATION.x)
8001 .y(FOCUSED_WINDOW_LOCATION.y))
8002 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008003 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008004 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008005 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008006 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008007 // We consumed all events, so no ANR
8008 ASSERT_TRUE(mDispatcher->waitForIdle());
8009 mFakePolicy->assertNotifyAnrWasNotCalled();
8010
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008012 injectMotionEvent(*mDispatcher,
8013 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8014 AINPUT_SOURCE_TOUCHSCREEN)
8015 .pointer(PointerBuilder(0, ToolType::FINGER)
8016 .x(FOCUSED_WINDOW_LOCATION.x)
8017 .y(FOCUSED_WINDOW_LOCATION.y))
8018 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008019 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8020 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021
8022 const std::chrono::duration timeout =
8023 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008024 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008025
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008026 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008027 mFocusedWindow->consumeMotionDown();
8028 // This cancel is generated because the connection was unresponsive
8029 mFocusedWindow->consumeMotionCancel();
8030 mFocusedWindow->assertNoEvents();
8031 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008032 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008033 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8034 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008035 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008036}
8037
8038// If we have 2 windows with identical timeouts that are both unresponsive,
8039// it doesn't matter which order they should have ANR.
8040// But we should receive ANR for both.
8041TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8042 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008043 mUnfocusedWindow->setDispatchingTimeout(
8044 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008045 mDispatcher->onWindowInfosChanged(
8046 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008047
8048 tapOnFocusedWindow();
8049 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008050 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008051 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8052 mFocusedWindow->getDispatchingTimeout(
8053 DISPATCHING_TIMEOUT)),
8054 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8055
8056 ASSERT_THAT(anrConnectionTokens,
8057 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8058 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008059
8060 ASSERT_TRUE(mDispatcher->waitForIdle());
8061 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008062
8063 mFocusedWindow->consumeMotionDown();
8064 mFocusedWindow->consumeMotionUp();
8065 mUnfocusedWindow->consumeMotionOutside();
8066
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008067 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8068 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008069
8070 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008071 ASSERT_THAT(responsiveTokens,
8072 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8073 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008074 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008075}
8076
8077// If a window is already not responding, the second tap on the same window should be ignored.
8078// We should also log an error to account for the dropped event (not tested here).
8079// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8080TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8081 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008082 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008083 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008084 // Receive the events, but don't respond
8085 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8086 ASSERT_TRUE(downEventSequenceNum);
8087 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8088 ASSERT_TRUE(upEventSequenceNum);
8089 const std::chrono::duration timeout =
8090 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008091 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008092
8093 // Tap once again
8094 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008095 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008096 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008097 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008098 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008099 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008100 FOCUSED_WINDOW_LOCATION));
8101 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8102 // valid touch target
8103 mUnfocusedWindow->assertNoEvents();
8104
8105 // Consume the first tap
8106 mFocusedWindow->finishEvent(*downEventSequenceNum);
8107 mFocusedWindow->finishEvent(*upEventSequenceNum);
8108 ASSERT_TRUE(mDispatcher->waitForIdle());
8109 // The second tap did not go to the focused window
8110 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008111 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008112 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8113 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008114 mFakePolicy->assertNotifyAnrWasNotCalled();
8115}
8116
8117// If you tap outside of all windows, there will not be ANR
8118TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008119 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008120 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008121 LOCATION_OUTSIDE_ALL_WINDOWS));
8122 ASSERT_TRUE(mDispatcher->waitForIdle());
8123 mFakePolicy->assertNotifyAnrWasNotCalled();
8124}
8125
8126// Since the focused window is paused, tapping on it should not produce any events
8127TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8128 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008129 mDispatcher->onWindowInfosChanged(
8130 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008131
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008132 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008133 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008134 FOCUSED_WINDOW_LOCATION));
8135
8136 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8137 ASSERT_TRUE(mDispatcher->waitForIdle());
8138 // Should not ANR because the window is paused, and touches shouldn't go to it
8139 mFakePolicy->assertNotifyAnrWasNotCalled();
8140
8141 mFocusedWindow->assertNoEvents();
8142 mUnfocusedWindow->assertNoEvents();
8143}
8144
8145/**
8146 * 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 -07008147 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008148 * If a different window becomes focused at this time, the key should go to that window instead.
8149 *
8150 * Warning!!!
8151 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8152 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008153 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008154 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8155 *
8156 * If that value changes, this test should also change.
8157 */
8158TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8159 // Set a long ANR timeout to prevent it from triggering
8160 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008161 mDispatcher->onWindowInfosChanged(
8162 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008163
8164 tapOnUnfocusedWindow();
8165 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8166 ASSERT_TRUE(downSequenceNum);
8167 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8168 ASSERT_TRUE(upSequenceNum);
8169 // Don't finish the events yet, and send a key
8170 // Injection will succeed because we will eventually give up and send the key to the focused
8171 // window even if motions are still being processed.
8172
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008173 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008174 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8175 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008177 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008178 // and the key remains pending, waiting for the touch events to be processed.
8179 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8180 // under the hood.
8181 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8182 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008183
8184 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008185 mFocusedWindow->setFocusable(false);
8186 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008187 mDispatcher->onWindowInfosChanged(
8188 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008189 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008190
8191 // Focus events should precede the key events
8192 mUnfocusedWindow->consumeFocusEvent(true);
8193 mFocusedWindow->consumeFocusEvent(false);
8194
8195 // Finish the tap events, which should unblock dispatcher
8196 mUnfocusedWindow->finishEvent(*downSequenceNum);
8197 mUnfocusedWindow->finishEvent(*upSequenceNum);
8198
8199 // Now that all queues are cleared and no backlog in the connections, the key event
8200 // can finally go to the newly focused "mUnfocusedWindow".
8201 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8202 mFocusedWindow->assertNoEvents();
8203 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008204 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008205}
8206
8207// When the touch stream is split across 2 windows, and one of them does not respond,
8208// then ANR should be raised and the touch should be canceled for the unresponsive window.
8209// The other window should not be affected by that.
8210TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8211 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008212 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8213 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8214 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008215 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008216 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008217
8218 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008219 mDispatcher->notifyMotion(
8220 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8221 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008222
8223 const std::chrono::duration timeout =
8224 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008225 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008226
8227 mUnfocusedWindow->consumeMotionDown();
8228 mFocusedWindow->consumeMotionDown();
8229 // Focused window may or may not receive ACTION_MOVE
8230 // But it should definitely receive ACTION_CANCEL due to the ANR
8231 InputEvent* event;
8232 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8233 ASSERT_TRUE(moveOrCancelSequenceNum);
8234 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8235 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008236 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008237 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8238 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8239 mFocusedWindow->consumeMotionCancel();
8240 } else {
8241 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8242 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008243 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008244 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8245 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008246
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008247 mUnfocusedWindow->assertNoEvents();
8248 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008249 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008250}
8251
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008252/**
8253 * If we have no focused window, and a key comes in, we start the ANR timer.
8254 * The focused application should add a focused window before the timer runs out to prevent ANR.
8255 *
8256 * If the user touches another application during this time, the key should be dropped.
8257 * Next, if a new focused window comes in, without toggling the focused application,
8258 * then no ANR should occur.
8259 *
8260 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8261 * but in some cases the policy may not update the focused application.
8262 */
8263TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8264 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8265 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008266 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008267 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8268 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8269 mFocusedWindow->setFocusable(false);
8270
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008271 mDispatcher->onWindowInfosChanged(
8272 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008273 mFocusedWindow->consumeFocusEvent(false);
8274
8275 // Send a key. The ANR timer should start because there is no focused window.
8276 // 'focusedApplication' will get blamed if this timer completes.
8277 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008278 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008279 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8280 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008281 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008283
8284 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8285 // then the injected touches won't cause the focused event to get dropped.
8286 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8287 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8288 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8289 // For this test, it means that the key would get delivered to the window once it becomes
8290 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008291 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008292
8293 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8295 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8296 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008297
8298 // We do not consume the motion right away, because that would require dispatcher to first
8299 // process (== drop) the key event, and by that time, ANR will be raised.
8300 // Set the focused window first.
8301 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008302 mDispatcher->onWindowInfosChanged(
8303 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008304 setFocusedWindow(mFocusedWindow);
8305 mFocusedWindow->consumeFocusEvent(true);
8306 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8307 // to another application. This could be a bug / behaviour in the policy.
8308
8309 mUnfocusedWindow->consumeMotionDown();
8310
8311 ASSERT_TRUE(mDispatcher->waitForIdle());
8312 // Should not ANR because we actually have a focused window. It was just added too slowly.
8313 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8314}
8315
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008316// These tests ensure we cannot send touch events to a window that's positioned behind a window
8317// that has feature NO_INPUT_CHANNEL.
8318// Layout:
8319// Top (closest to user)
8320// mNoInputWindow (above all windows)
8321// mBottomWindow
8322// Bottom (furthest from user)
8323class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8324 virtual void SetUp() override {
8325 InputDispatcherTest::SetUp();
8326
8327 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008328 mNoInputWindow =
8329 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8330 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008331 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008332 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008333 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8334 // It's perfectly valid for this window to not have an associated input channel
8335
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008336 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8337 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008338 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8339
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008340 mDispatcher->onWindowInfosChanged(
8341 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008342 }
8343
8344protected:
8345 std::shared_ptr<FakeApplicationHandle> mApplication;
8346 sp<FakeWindowHandle> mNoInputWindow;
8347 sp<FakeWindowHandle> mBottomWindow;
8348};
8349
8350TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8351 PointF touchedPoint = {10, 10};
8352
Prabir Pradhan678438e2023-04-13 19:32:51 +00008353 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8354 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8355 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008356
8357 mNoInputWindow->assertNoEvents();
8358 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8359 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8360 // and therefore should prevent mBottomWindow from receiving touches
8361 mBottomWindow->assertNoEvents();
8362}
8363
8364/**
8365 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8366 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8367 */
8368TEST_F(InputDispatcherMultiWindowOcclusionTests,
8369 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008370 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8371 "Window with input channel and NO_INPUT_CHANNEL",
8372 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008373
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008374 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008375 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008376 mDispatcher->onWindowInfosChanged(
8377 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008378
8379 PointF touchedPoint = {10, 10};
8380
Prabir Pradhan678438e2023-04-13 19:32:51 +00008381 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8382 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8383 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008384
8385 mNoInputWindow->assertNoEvents();
8386 mBottomWindow->assertNoEvents();
8387}
8388
Vishnu Nair958da932020-08-21 17:12:37 -07008389class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8390protected:
8391 std::shared_ptr<FakeApplicationHandle> mApp;
8392 sp<FakeWindowHandle> mWindow;
8393 sp<FakeWindowHandle> mMirror;
8394
8395 virtual void SetUp() override {
8396 InputDispatcherTest::SetUp();
8397 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008398 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8399 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8400 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008401 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8402 mWindow->setFocusable(true);
8403 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008404 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008405 }
8406};
8407
8408TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8409 // Request focus on a mirrored window
8410 setFocusedWindow(mMirror);
8411
8412 // window gets focused
8413 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008415 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008416 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8417}
8418
8419// A focused & mirrored window remains focused only if the window and its mirror are both
8420// focusable.
8421TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8422 setFocusedWindow(mMirror);
8423
8424 // window gets focused
8425 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008427 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008428 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008430 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008431 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8432
8433 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008434 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008435
8436 // window loses focus since one of the windows associated with the token in not focusable
8437 mWindow->consumeFocusEvent(false);
8438
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008439 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008440 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008441 mWindow->assertNoEvents();
8442}
8443
8444// A focused & mirrored window remains focused until the window and its mirror both become
8445// invisible.
8446TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8447 setFocusedWindow(mMirror);
8448
8449 // window gets focused
8450 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008452 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008453 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008455 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008456 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8457
8458 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008459 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008460
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008462 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008463 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008465 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008466 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8467
8468 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008469 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008470
8471 // window loses focus only after all windows associated with the token become invisible.
8472 mWindow->consumeFocusEvent(false);
8473
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008474 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008475 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008476 mWindow->assertNoEvents();
8477}
8478
8479// A focused & mirrored window remains focused until both windows are removed.
8480TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8481 setFocusedWindow(mMirror);
8482
8483 // window gets focused
8484 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008486 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008487 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008489 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008490 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8491
8492 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008493 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008494
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008496 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008497 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008499 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008500 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8501
8502 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008503 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008504 mWindow->consumeFocusEvent(false);
8505
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008506 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008507 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008508 mWindow->assertNoEvents();
8509}
8510
8511// Focus request can be pending until one window becomes visible.
8512TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8513 // Request focus on an invisible mirror.
8514 mWindow->setVisible(false);
8515 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008516 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008517 setFocusedWindow(mMirror);
8518
8519 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008521 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8522 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008523
8524 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008525 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008526
8527 // window gets focused
8528 mWindow->consumeFocusEvent(true);
8529 // window gets the pending key event
8530 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8531}
Prabir Pradhan99987712020-11-10 18:43:05 -08008532
8533class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8534protected:
8535 std::shared_ptr<FakeApplicationHandle> mApp;
8536 sp<FakeWindowHandle> mWindow;
8537 sp<FakeWindowHandle> mSecondWindow;
8538
8539 void SetUp() override {
8540 InputDispatcherTest::SetUp();
8541 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008542 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008543 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008544 mSecondWindow =
8545 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008546 mSecondWindow->setFocusable(true);
8547
8548 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008549 mDispatcher->onWindowInfosChanged(
8550 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008551
8552 setFocusedWindow(mWindow);
8553 mWindow->consumeFocusEvent(true);
8554 }
8555
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008556 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008557 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008558 }
8559
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008560 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8561 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008562 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008563 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8564 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008565 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008566 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008567 }
8568};
8569
8570TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8571 // Ensure that capture cannot be obtained for unfocused windows.
8572 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8573 mFakePolicy->assertSetPointerCaptureNotCalled();
8574 mSecondWindow->assertNoEvents();
8575
8576 // Ensure that capture can be enabled from the focus window.
8577 requestAndVerifyPointerCapture(mWindow, true);
8578
8579 // Ensure that capture cannot be disabled from a window that does not have capture.
8580 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8581 mFakePolicy->assertSetPointerCaptureNotCalled();
8582
8583 // Ensure that capture can be disabled from the window with capture.
8584 requestAndVerifyPointerCapture(mWindow, false);
8585}
8586
8587TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008588 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008589
8590 setFocusedWindow(mSecondWindow);
8591
8592 // Ensure that the capture disabled event was sent first.
8593 mWindow->consumeCaptureEvent(false);
8594 mWindow->consumeFocusEvent(false);
8595 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008596 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008597
8598 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008599 notifyPointerCaptureChanged({});
8600 notifyPointerCaptureChanged(request);
8601 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008602 mWindow->assertNoEvents();
8603 mSecondWindow->assertNoEvents();
8604 mFakePolicy->assertSetPointerCaptureNotCalled();
8605}
8606
8607TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008608 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008609
8610 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008611 notifyPointerCaptureChanged({});
8612 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008613
8614 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008615 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008616 mWindow->consumeCaptureEvent(false);
8617 mWindow->assertNoEvents();
8618}
8619
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008620TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8621 requestAndVerifyPointerCapture(mWindow, true);
8622
8623 // The first window loses focus.
8624 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008625 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008626 mWindow->consumeCaptureEvent(false);
8627
8628 // Request Pointer Capture from the second window before the notification from InputReader
8629 // arrives.
8630 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008631 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008632
8633 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008634 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008635
8636 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008637 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008638
8639 mSecondWindow->consumeFocusEvent(true);
8640 mSecondWindow->consumeCaptureEvent(true);
8641}
8642
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008643TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8644 // App repeatedly enables and disables capture.
8645 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8646 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8647 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8648 mFakePolicy->assertSetPointerCaptureCalled(false);
8649 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8650 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8651
8652 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8653 // first request is now stale, this should do nothing.
8654 notifyPointerCaptureChanged(firstRequest);
8655 mWindow->assertNoEvents();
8656
8657 // InputReader notifies that the second request was enabled.
8658 notifyPointerCaptureChanged(secondRequest);
8659 mWindow->consumeCaptureEvent(true);
8660}
8661
Prabir Pradhan7092e262022-05-03 16:51:09 +00008662TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8663 requestAndVerifyPointerCapture(mWindow, true);
8664
8665 // App toggles pointer capture off and on.
8666 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8667 mFakePolicy->assertSetPointerCaptureCalled(false);
8668
8669 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8670 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8671
8672 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8673 // preceding "disable" request.
8674 notifyPointerCaptureChanged(enableRequest);
8675
8676 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8677 // any notifications.
8678 mWindow->assertNoEvents();
8679}
8680
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008681/**
8682 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8683 * mouse movements don't affect the previous mouse hovering state.
8684 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8685 * HOVER_MOVE events).
8686 */
8687TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8688 // Mouse hover on the window
8689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8690 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8691 .build());
8692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8693 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8694 .build());
8695
8696 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8697 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8698
8699 // Start pointer capture
8700 requestAndVerifyPointerCapture(mWindow, true);
8701
8702 // Send some relative mouse movements and receive them in the window.
8703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8704 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8705 .build());
8706 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8707 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8708
8709 // Stop pointer capture
8710 requestAndVerifyPointerCapture(mWindow, false);
8711
8712 // Continue hovering on the window
8713 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8714 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8715 .build());
8716 mWindow->consumeMotionEvent(
8717 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8718
8719 mWindow->assertNoEvents();
8720}
8721
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008722class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8723protected:
8724 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008725
8726 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8727 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8728
8729 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8730 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8731
8732 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8733 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8734 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8735 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8736 MAXIMUM_OBSCURING_OPACITY);
8737
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008738 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8739 static constexpr gui::Uid APP_B_UID{10002};
8740 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008741
8742 sp<FakeWindowHandle> mTouchWindow;
8743
8744 virtual void SetUp() override {
8745 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008746 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008747 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8748 }
8749
8750 virtual void TearDown() override {
8751 InputDispatcherTest::TearDown();
8752 mTouchWindow.clear();
8753 }
8754
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008755 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008756 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008757 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008758 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008759 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008760 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008761 return window;
8762 }
8763
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008764 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008765 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8766 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008767 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008768 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008769 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008770 return window;
8771 }
8772
8773 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008774 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8775 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8776 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008777 }
8778};
8779
8780TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008781 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008782 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008783 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008784
8785 touch();
8786
8787 mTouchWindow->assertNoEvents();
8788}
8789
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008790TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008791 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8792 const sp<FakeWindowHandle>& w =
8793 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008794 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008795
8796 touch();
8797
8798 mTouchWindow->assertNoEvents();
8799}
8800
8801TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008802 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8803 const sp<FakeWindowHandle>& w =
8804 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008805 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008806
8807 touch();
8808
8809 w->assertNoEvents();
8810}
8811
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008812TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008813 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008814 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008815
8816 touch();
8817
8818 mTouchWindow->consumeAnyMotionDown();
8819}
8820
8821TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008822 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008823 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008824 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008825 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008826
8827 touch({PointF{100, 100}});
8828
8829 mTouchWindow->consumeAnyMotionDown();
8830}
8831
8832TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008833 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008834 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008835 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008836
8837 touch();
8838
8839 mTouchWindow->consumeAnyMotionDown();
8840}
8841
8842TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8843 const sp<FakeWindowHandle>& w =
8844 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008845 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008846
8847 touch();
8848
8849 mTouchWindow->consumeAnyMotionDown();
8850}
8851
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008852TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8853 const sp<FakeWindowHandle>& w =
8854 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008855 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008856
8857 touch();
8858
8859 w->assertNoEvents();
8860}
8861
8862/**
8863 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8864 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8865 * window, the occluding window will still receive ACTION_OUTSIDE event.
8866 */
8867TEST_F(InputDispatcherUntrustedTouchesTest,
8868 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8869 const sp<FakeWindowHandle>& w =
8870 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008871 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008872 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008873
8874 touch();
8875
8876 w->consumeMotionOutside();
8877}
8878
8879TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8880 const sp<FakeWindowHandle>& w =
8881 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008882 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008883 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008884
8885 touch();
8886
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008887 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008888}
8889
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008890TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008891 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008892 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8893 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008894 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008895
8896 touch();
8897
8898 mTouchWindow->consumeAnyMotionDown();
8899}
8900
8901TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8902 const sp<FakeWindowHandle>& w =
8903 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8904 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008905 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008906
8907 touch();
8908
8909 mTouchWindow->consumeAnyMotionDown();
8910}
8911
8912TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008913 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008914 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8915 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008916 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008917
8918 touch();
8919
8920 mTouchWindow->assertNoEvents();
8921}
8922
8923TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8924 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8925 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008926 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8927 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008928 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008929 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8930 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008931 mDispatcher->onWindowInfosChanged(
8932 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008933
8934 touch();
8935
8936 mTouchWindow->assertNoEvents();
8937}
8938
8939TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8940 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8941 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008942 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8943 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008944 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008945 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8946 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008947 mDispatcher->onWindowInfosChanged(
8948 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008949
8950 touch();
8951
8952 mTouchWindow->consumeAnyMotionDown();
8953}
8954
8955TEST_F(InputDispatcherUntrustedTouchesTest,
8956 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8957 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008958 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8959 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008960 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008961 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8962 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008963 mDispatcher->onWindowInfosChanged(
8964 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008965
8966 touch();
8967
8968 mTouchWindow->consumeAnyMotionDown();
8969}
8970
8971TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8972 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008973 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8974 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008975 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008976 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8977 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008978 mDispatcher->onWindowInfosChanged(
8979 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008980
8981 touch();
8982
8983 mTouchWindow->assertNoEvents();
8984}
8985
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008986TEST_F(InputDispatcherUntrustedTouchesTest,
8987 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8988 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008989 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8990 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008991 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008992 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8993 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008994 mDispatcher->onWindowInfosChanged(
8995 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008996
8997 touch();
8998
8999 mTouchWindow->assertNoEvents();
9000}
9001
9002TEST_F(InputDispatcherUntrustedTouchesTest,
9003 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9004 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009005 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9006 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009007 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009008 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9009 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009010 mDispatcher->onWindowInfosChanged(
9011 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009012
9013 touch();
9014
9015 mTouchWindow->consumeAnyMotionDown();
9016}
9017
9018TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9019 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009020 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9021 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009022 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009023
9024 touch();
9025
9026 mTouchWindow->consumeAnyMotionDown();
9027}
9028
9029TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9030 const sp<FakeWindowHandle>& w =
9031 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009032 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009033
9034 touch();
9035
9036 mTouchWindow->consumeAnyMotionDown();
9037}
9038
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009039TEST_F(InputDispatcherUntrustedTouchesTest,
9040 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9041 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9042 const sp<FakeWindowHandle>& w =
9043 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009044 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009045
9046 touch();
9047
9048 mTouchWindow->assertNoEvents();
9049}
9050
9051TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9052 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9053 const sp<FakeWindowHandle>& w =
9054 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009055 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009056
9057 touch();
9058
9059 mTouchWindow->consumeAnyMotionDown();
9060}
9061
9062TEST_F(InputDispatcherUntrustedTouchesTest,
9063 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9064 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9065 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009066 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9067 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009068 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009069
9070 touch();
9071
9072 mTouchWindow->consumeAnyMotionDown();
9073}
9074
9075TEST_F(InputDispatcherUntrustedTouchesTest,
9076 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9077 const sp<FakeWindowHandle>& w1 =
9078 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9079 OPACITY_BELOW_THRESHOLD);
9080 const sp<FakeWindowHandle>& w2 =
9081 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9082 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009083 mDispatcher->onWindowInfosChanged(
9084 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009085
9086 touch();
9087
9088 mTouchWindow->assertNoEvents();
9089}
9090
9091/**
9092 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9093 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9094 * (which alone would result in allowing touches) does not affect the blocking behavior.
9095 */
9096TEST_F(InputDispatcherUntrustedTouchesTest,
9097 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9098 const sp<FakeWindowHandle>& wB =
9099 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9100 OPACITY_BELOW_THRESHOLD);
9101 const sp<FakeWindowHandle>& wC =
9102 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9103 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009104 mDispatcher->onWindowInfosChanged(
9105 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009106
9107 touch();
9108
9109 mTouchWindow->assertNoEvents();
9110}
9111
9112/**
9113 * This test is testing that a window from a different UID but with same application token doesn't
9114 * block the touch. Apps can share the application token for close UI collaboration for example.
9115 */
9116TEST_F(InputDispatcherUntrustedTouchesTest,
9117 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9118 const sp<FakeWindowHandle>& w =
9119 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9120 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009121 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009122
9123 touch();
9124
9125 mTouchWindow->consumeAnyMotionDown();
9126}
9127
arthurhungb89ccb02020-12-30 16:19:01 +08009128class InputDispatcherDragTests : public InputDispatcherTest {
9129protected:
9130 std::shared_ptr<FakeApplicationHandle> mApp;
9131 sp<FakeWindowHandle> mWindow;
9132 sp<FakeWindowHandle> mSecondWindow;
9133 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009134 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009135 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9136 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009137
9138 void SetUp() override {
9139 InputDispatcherTest::SetUp();
9140 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009141 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009142 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009143
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009144 mSecondWindow =
9145 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009146 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009147
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009148 mSpyWindow =
9149 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009150 mSpyWindow->setSpy(true);
9151 mSpyWindow->setTrustedOverlay(true);
9152 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9153
arthurhungb89ccb02020-12-30 16:19:01 +08009154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009155 mDispatcher->onWindowInfosChanged(
9156 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9157 {},
9158 0,
9159 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009160 }
9161
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009162 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9163 switch (fromSource) {
9164 case AINPUT_SOURCE_TOUCHSCREEN:
9165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009166 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009167 ADISPLAY_ID_DEFAULT, {50, 50}))
9168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9169 break;
9170 case AINPUT_SOURCE_STYLUS:
9171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009172 injectMotionEvent(*mDispatcher,
9173 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9174 AINPUT_SOURCE_STYLUS)
9175 .buttonState(
9176 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9177 .pointer(PointerBuilder(0, ToolType::STYLUS)
9178 .x(50)
9179 .y(50))
9180 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009181 break;
9182 case AINPUT_SOURCE_MOUSE:
9183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009184 injectMotionEvent(*mDispatcher,
9185 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9186 AINPUT_SOURCE_MOUSE)
9187 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9188 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9189 ToolType::MOUSE)
9190 .x(50)
9191 .y(50))
9192 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009193 break;
9194 default:
9195 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9196 }
arthurhungb89ccb02020-12-30 16:19:01 +08009197
9198 // Window should receive motion event.
9199 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009200 // Spy window should also receive motion event
9201 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009202 }
9203
9204 // Start performing drag, we will create a drag window and transfer touch to it.
9205 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9206 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009207 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009208 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009209 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009210 }
arthurhungb89ccb02020-12-30 16:19:01 +08009211
9212 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009213 mDragWindow =
9214 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009215 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009216 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9217 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9218 {},
9219 0,
9220 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009221
9222 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009223 bool transferred =
9224 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009225 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009226 if (transferred) {
9227 mWindow->consumeMotionCancel();
9228 mDragWindow->consumeMotionDown();
9229 }
9230 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009231 }
9232};
9233
9234TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009235 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009236
9237 // Move on 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, {50, 50}))
9241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9242 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9243 mWindow->consumeDragEvent(false, 50, 50);
9244 mSecondWindow->assertNoEvents();
9245
9246 // Move to another 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, {150, 50}))
9250 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9251 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9252 mWindow->consumeDragEvent(true, 150, 50);
9253 mSecondWindow->consumeDragEvent(false, 50, 50);
9254
9255 // Move back to original window.
9256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009257 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009258 ADISPLAY_ID_DEFAULT, {50, 50}))
9259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9260 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9261 mWindow->consumeDragEvent(false, 50, 50);
9262 mSecondWindow->consumeDragEvent(true, -50, 50);
9263
9264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009265 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9266 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9268 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9269 mWindow->assertNoEvents();
9270 mSecondWindow->assertNoEvents();
9271}
9272
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009273TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009274 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009275
9276 // No cancel event after drag start
9277 mSpyWindow->assertNoEvents();
9278
9279 const MotionEvent secondFingerDownEvent =
9280 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9281 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009282 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9283 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009284 .build();
9285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009286 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009287 InputEventInjectionSync::WAIT_FOR_RESULT))
9288 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9289
9290 // Receives cancel for first pointer after next pointer down
9291 mSpyWindow->consumeMotionCancel();
9292 mSpyWindow->consumeMotionDown();
9293
9294 mSpyWindow->assertNoEvents();
9295}
9296
arthurhungf452d0b2021-01-06 00:19:52 +08009297TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009298 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009299
9300 // Move on 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, {50, 50}))
9304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9305 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9306 mWindow->consumeDragEvent(false, 50, 50);
9307 mSecondWindow->assertNoEvents();
9308
9309 // Move to another window.
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009311 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009312 ADISPLAY_ID_DEFAULT, {150, 50}))
9313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9314 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9315 mWindow->consumeDragEvent(true, 150, 50);
9316 mSecondWindow->consumeDragEvent(false, 50, 50);
9317
9318 // drop to another window.
9319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009320 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009321 {150, 50}))
9322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9323 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009324 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009325 mWindow->assertNoEvents();
9326 mSecondWindow->assertNoEvents();
9327}
9328
arthurhung6d4bed92021-03-17 11:59:33 +08009329TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009330 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009331
9332 // Move on window and keep button pressed.
9333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009334 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009335 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9336 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009337 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009338 .build()))
9339 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9340 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9341 mWindow->consumeDragEvent(false, 50, 50);
9342 mSecondWindow->assertNoEvents();
9343
9344 // Move to another window and release button, expect to drop item.
9345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009346 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009347 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9348 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009349 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009350 .build()))
9351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9352 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9353 mWindow->assertNoEvents();
9354 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009355 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009356
9357 // nothing to the window.
9358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009359 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009360 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9361 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009362 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009363 .build()))
9364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9365 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9366 mWindow->assertNoEvents();
9367 mSecondWindow->assertNoEvents();
9368}
9369
Arthur Hung54745652022-04-20 07:17:41 +00009370TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009371 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009372
9373 // Set second window invisible.
9374 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009375 mDispatcher->onWindowInfosChanged(
9376 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009377
9378 // Move on 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, {50, 50}))
9382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9383 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9384 mWindow->consumeDragEvent(false, 50, 50);
9385 mSecondWindow->assertNoEvents();
9386
9387 // Move to another window.
9388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009389 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009390 ADISPLAY_ID_DEFAULT, {150, 50}))
9391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9392 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9393 mWindow->consumeDragEvent(true, 150, 50);
9394 mSecondWindow->assertNoEvents();
9395
9396 // drop to another window.
9397 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009398 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009399 {150, 50}))
9400 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9401 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009402 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009403 mWindow->assertNoEvents();
9404 mSecondWindow->assertNoEvents();
9405}
9406
Arthur Hung54745652022-04-20 07:17:41 +00009407TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009408 // Ensure window could track pointerIds if it didn't support split touch.
9409 mWindow->setPreventSplitting(true);
9410
Arthur Hung54745652022-04-20 07:17:41 +00009411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009412 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009413 {50, 50}))
9414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9415 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9416
9417 const MotionEvent secondFingerDownEvent =
9418 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9419 .displayId(ADISPLAY_ID_DEFAULT)
9420 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009421 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9422 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009423 .build();
9424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009425 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009426 InputEventInjectionSync::WAIT_FOR_RESULT))
9427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009428 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009429
9430 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009431 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009432}
9433
9434TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9435 // First down on second window.
9436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009437 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009438 {150, 50}))
9439 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9440
9441 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9442
9443 // Second down on first window.
9444 const MotionEvent secondFingerDownEvent =
9445 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9446 .displayId(ADISPLAY_ID_DEFAULT)
9447 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009448 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9449 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009450 .build();
9451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009452 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009453 InputEventInjectionSync::WAIT_FOR_RESULT))
9454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9455 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9456
9457 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009458 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009459
9460 // Move on window.
9461 const MotionEvent secondFingerMoveEvent =
9462 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9463 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009464 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9465 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009466 .build();
9467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009468 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009469 InputEventInjectionSync::WAIT_FOR_RESULT));
9470 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9471 mWindow->consumeDragEvent(false, 50, 50);
9472 mSecondWindow->consumeMotionMove();
9473
9474 // Release the drag pointer should perform drop.
9475 const MotionEvent secondFingerUpEvent =
9476 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9477 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009478 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9479 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009480 .build();
9481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009482 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009483 InputEventInjectionSync::WAIT_FOR_RESULT));
9484 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009485 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009486 mWindow->assertNoEvents();
9487 mSecondWindow->consumeMotionMove();
9488}
9489
Arthur Hung3915c1f2022-05-31 07:17:17 +00009490TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009491 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009492
9493 // Update window of second display.
9494 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009495 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009496 mDispatcher->onWindowInfosChanged(
9497 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9498 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9499 {},
9500 0,
9501 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009502
9503 // Let second display has a touch state.
9504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009505 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009506 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9507 AINPUT_SOURCE_TOUCHSCREEN)
9508 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009509 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009510 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009511 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009512 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009513 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009514 mDispatcher->onWindowInfosChanged(
9515 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9516 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9517 {},
9518 0,
9519 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009520
9521 // Move on 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, {50, 50}))
9525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9526 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9527 mWindow->consumeDragEvent(false, 50, 50);
9528 mSecondWindow->assertNoEvents();
9529
9530 // Move to another window.
9531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009532 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009533 ADISPLAY_ID_DEFAULT, {150, 50}))
9534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9535 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9536 mWindow->consumeDragEvent(true, 150, 50);
9537 mSecondWindow->consumeDragEvent(false, 50, 50);
9538
9539 // drop to another window.
9540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009541 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009542 {150, 50}))
9543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9544 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009545 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009546 mWindow->assertNoEvents();
9547 mSecondWindow->assertNoEvents();
9548}
9549
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009550TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9551 startDrag(true, AINPUT_SOURCE_MOUSE);
9552 // Move on window.
9553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009554 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009555 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9556 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009557 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009558 .x(50)
9559 .y(50))
9560 .build()))
9561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9562 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9563 mWindow->consumeDragEvent(false, 50, 50);
9564 mSecondWindow->assertNoEvents();
9565
9566 // Move to another window.
9567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009568 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009569 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9570 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009571 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009572 .x(150)
9573 .y(50))
9574 .build()))
9575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9576 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9577 mWindow->consumeDragEvent(true, 150, 50);
9578 mSecondWindow->consumeDragEvent(false, 50, 50);
9579
9580 // drop to another window.
9581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009582 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009583 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9584 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009585 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009586 .x(150)
9587 .y(50))
9588 .build()))
9589 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9590 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009591 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009592 mWindow->assertNoEvents();
9593 mSecondWindow->assertNoEvents();
9594}
9595
Linnan Li5af92f92023-07-14 14:36:22 +08009596/**
9597 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9598 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9599 */
9600TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9601 // Down on second window
9602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9603 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9604 {150, 50}))
9605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9606
9607 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9608 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9609
9610 // Down on first window
9611 const MotionEvent secondFingerDownEvent =
9612 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9613 .displayId(ADISPLAY_ID_DEFAULT)
9614 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9615 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9616 .build();
9617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9618 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9619 InputEventInjectionSync::WAIT_FOR_RESULT))
9620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9621 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9622 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9623 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9624
9625 // Start drag on first window
9626 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9627
9628 // Trigger cancel
9629 mDispatcher->cancelCurrentTouch();
9630 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9631 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9632 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9633
9634 ASSERT_TRUE(mDispatcher->waitForIdle());
9635 // The D&D finished with nullptr
9636 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9637
9638 // Remove drag window
9639 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9640
9641 // Inject a simple gesture, ensure dispatcher not crashed
9642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9643 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9644 PointF{50, 50}))
9645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9646 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9647
9648 const MotionEvent moveEvent =
9649 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9650 .displayId(ADISPLAY_ID_DEFAULT)
9651 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9652 .build();
9653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9654 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9655 InputEventInjectionSync::WAIT_FOR_RESULT))
9656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9657 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9658
9659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9660 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9661 {50, 50}))
9662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9663 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9664}
9665
Vishnu Nair062a8672021-09-03 16:07:44 -07009666class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9667
9668TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9671 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009672 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009673 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9674 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009675 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009676 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009677 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009678
9679 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009680 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009681 window->assertNoEvents();
9682
Prabir Pradhan678438e2023-04-13 19:32:51 +00009683 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9684 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009685 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9686 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009687 window->assertNoEvents();
9688
9689 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009690 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009691 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009692
Prabir Pradhan678438e2023-04-13 19:32:51 +00009693 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009694 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9695
Prabir Pradhan678438e2023-04-13 19:32:51 +00009696 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9697 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009698 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9699 window->assertNoEvents();
9700}
9701
9702TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9703 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9704 std::make_shared<FakeApplicationHandle>();
9705 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009706 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9707 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009708 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009709 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009710 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009712 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9713 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009714 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009715 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009716 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9717 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009718 mDispatcher->onWindowInfosChanged(
9719 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009720 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009721 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009722
9723 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009724 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009725 window->assertNoEvents();
9726
Prabir Pradhan678438e2023-04-13 19:32:51 +00009727 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9728 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009729 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9730 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009731 window->assertNoEvents();
9732
9733 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009734 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009735 mDispatcher->onWindowInfosChanged(
9736 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009737
Prabir Pradhan678438e2023-04-13 19:32:51 +00009738 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009739 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9740
Prabir Pradhan678438e2023-04-13 19:32:51 +00009741 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9742 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009743 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9744 window->assertNoEvents();
9745}
9746
9747TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9748 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9749 std::make_shared<FakeApplicationHandle>();
9750 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009751 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9752 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009753 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009754 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009755 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9758 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009759 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009760 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009761 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9762 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009763 mDispatcher->onWindowInfosChanged(
9764 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009765 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009766 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009767
9768 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009769 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009770 window->assertNoEvents();
9771
Prabir Pradhan678438e2023-04-13 19:32:51 +00009772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9773 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009774 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9775 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009776 window->assertNoEvents();
9777
9778 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009779 mDispatcher->onWindowInfosChanged(
9780 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009781
Prabir Pradhan678438e2023-04-13 19:32:51 +00009782 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009783 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9784
Prabir Pradhan678438e2023-04-13 19:32:51 +00009785 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9786 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009787 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9788 window->assertNoEvents();
9789}
9790
Antonio Kantekf16f2832021-09-28 04:39:20 +00009791class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9792protected:
9793 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009794 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009795 sp<FakeWindowHandle> mWindow;
9796 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009797 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009798
9799 void SetUp() override {
9800 InputDispatcherTest::SetUp();
9801
9802 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009803 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009804 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009805 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009806 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009807 mSecondWindow =
9808 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009809 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009810 mThirdWindow =
9811 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9812 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9813 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009814
9815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009816 mDispatcher->onWindowInfosChanged(
9817 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9818 {},
9819 0,
9820 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009821 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009822 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009823
Antonio Kantek15beb512022-06-13 22:35:41 +00009824 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009825 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009826 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009827 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9828 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009829 mThirdWindow->assertNoEvents();
9830 }
9831
9832 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9833 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009834 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009835 SECOND_DISPLAY_ID)) {
9836 mWindow->assertNoEvents();
9837 mSecondWindow->assertNoEvents();
9838 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009839 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009840 }
9841
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009842 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009843 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009844 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9845 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009846 mWindow->consumeTouchModeEvent(inTouchMode);
9847 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009848 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009849 }
9850};
9851
Antonio Kantek26defcf2022-02-08 01:12:27 +00009852TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009853 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009854 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9855 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009856 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009857}
9858
Antonio Kantek26defcf2022-02-08 01:12:27 +00009859TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9860 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009861 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009862 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009863 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009864 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009865 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009866 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009867 mWindow->assertNoEvents();
9868 mSecondWindow->assertNoEvents();
9869}
9870
9871TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9872 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009873 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009874 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009875 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009876 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009877 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009878}
9879
Antonio Kantekf16f2832021-09-28 04:39:20 +00009880TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009881 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009882 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9883 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009884 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009885 mWindow->assertNoEvents();
9886 mSecondWindow->assertNoEvents();
9887}
9888
Antonio Kantek15beb512022-06-13 22:35:41 +00009889TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9890 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9891 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9892 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009893 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009894 mWindow->assertNoEvents();
9895 mSecondWindow->assertNoEvents();
9896 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9897}
9898
Antonio Kantek48710e42022-03-24 14:19:30 -07009899TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9900 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9902 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009903 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9904 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9905
9906 // Then remove focus.
9907 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009908 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009909
9910 // Assert that caller can switch touch mode by owning one of the last interacted window.
9911 const WindowInfo& windowInfo = *mWindow->getInfo();
9912 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9913 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009914 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009915}
9916
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009917class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9918public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009919 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009920 std::shared_ptr<FakeApplicationHandle> application =
9921 std::make_shared<FakeApplicationHandle>();
9922 std::string name = "Fake Spy ";
9923 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009924 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9925 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009926 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009927 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009928 return spy;
9929 }
9930
9931 sp<FakeWindowHandle> createForeground() {
9932 std::shared_ptr<FakeApplicationHandle> application =
9933 std::make_shared<FakeApplicationHandle>();
9934 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009935 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9936 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009937 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009938 return window;
9939 }
9940
9941private:
9942 int mSpyCount{0};
9943};
9944
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009945using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009946/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009947 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9948 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009949TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009950 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009951 ScopedSilentDeath _silentDeath;
9952
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009953 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009954 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009955 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009956 ".* not a trusted overlay");
9957}
9958
9959/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009960 * Input injection into a display with a spy window but no foreground windows should succeed.
9961 */
9962TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009963 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009964 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009965
9966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009967 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9969 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9970}
9971
9972/**
9973 * Verify the order in which different input windows receive events. The touched foreground window
9974 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9975 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9976 * receive events before ones belows it.
9977 *
9978 * Here, we set up a scenario with four windows in the following Z order from the top:
9979 * spy1, spy2, window, spy3.
9980 * We then inject an event and verify that the foreground "window" receives it first, followed by
9981 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9982 * window.
9983 */
9984TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9985 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009986 auto spy1 = createSpy();
9987 auto spy2 = createSpy();
9988 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009989 mDispatcher->onWindowInfosChanged(
9990 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009991 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9992 const size_t numChannels = channels.size();
9993
Michael Wright8e9a8562022-02-09 13:44:29 +00009994 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009995 if (!epollFd.ok()) {
9996 FAIL() << "Failed to create epoll fd";
9997 }
9998
9999 for (size_t i = 0; i < numChannels; i++) {
10000 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10001 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10002 FAIL() << "Failed to add fd to epoll";
10003 }
10004 }
10005
10006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010007 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10009
10010 std::vector<size_t> eventOrder;
10011 std::vector<struct epoll_event> events(numChannels);
10012 for (;;) {
10013 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10014 (100ms).count());
10015 if (nFds < 0) {
10016 FAIL() << "Failed to call epoll_wait";
10017 }
10018 if (nFds == 0) {
10019 break; // epoll_wait timed out
10020 }
10021 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010022 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010023 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010024 channels[i]->consumeMotionDown();
10025 }
10026 }
10027
10028 // Verify the order in which the events were received.
10029 EXPECT_EQ(3u, eventOrder.size());
10030 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10031 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10032 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10033}
10034
10035/**
10036 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10037 */
10038TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10039 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010040 auto spy = createSpy();
10041 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010042 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010043
10044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010045 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10047 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10048 spy->assertNoEvents();
10049}
10050
10051/**
10052 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10053 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10054 * to the window.
10055 */
10056TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10057 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010058 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010059 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010060 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010061
10062 // Inject an event outside the spy window's touchable region.
10063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010064 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10066 window->consumeMotionDown();
10067 spy->assertNoEvents();
10068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010069 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10071 window->consumeMotionUp();
10072 spy->assertNoEvents();
10073
10074 // Inject an event inside the spy window's touchable region.
10075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010077 {5, 10}))
10078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10079 window->consumeMotionDown();
10080 spy->consumeMotionDown();
10081}
10082
10083/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010084 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010085 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010086 */
10087TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10088 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010089 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010090 auto spy = createSpy();
10091 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010092 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010093 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010094 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010095
10096 // Inject an event outside the spy window's frame and touchable region.
10097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010098 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010099 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10101 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010102 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010103}
10104
10105/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010106 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10107 * pointers that are down within its bounds.
10108 */
10109TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10110 auto windowLeft = createForeground();
10111 windowLeft->setFrame({0, 0, 100, 200});
10112 auto windowRight = createForeground();
10113 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010114 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010115 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010116 mDispatcher->onWindowInfosChanged(
10117 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010118
10119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010120 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010121 {50, 50}))
10122 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10123 windowLeft->consumeMotionDown();
10124 spy->consumeMotionDown();
10125
10126 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010127 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010128 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010129 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10130 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010131 .build();
10132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010133 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010134 InputEventInjectionSync::WAIT_FOR_RESULT))
10135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10136 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010137 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010138}
10139
10140/**
10141 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10142 * the spy should receive the second pointer with ACTION_DOWN.
10143 */
10144TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10145 auto window = createForeground();
10146 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010147 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010148 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010149 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010150
10151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010152 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010153 {50, 50}))
10154 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10155 window->consumeMotionDown();
10156 spyRight->assertNoEvents();
10157
10158 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010159 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010160 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010161 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10162 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010163 .build();
10164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010165 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010166 InputEventInjectionSync::WAIT_FOR_RESULT))
10167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010168 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010169 spyRight->consumeMotionDown();
10170}
10171
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010172/**
10173 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10174 * windows should be allowed to control split touch.
10175 */
10176TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010177 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010178 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010179 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010180 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010181
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010182 auto window = createForeground();
10183 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010184
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010185 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010186
10187 // First finger down, no window touched.
10188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010189 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010190 {100, 200}))
10191 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10192 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10193 window->assertNoEvents();
10194
10195 // Second finger down on window, the window should receive touch down.
10196 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010197 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010198 .displayId(ADISPLAY_ID_DEFAULT)
10199 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010200 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10201 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010202 .build();
10203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010204 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010205 InputEventInjectionSync::WAIT_FOR_RESULT))
10206 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10207
10208 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010209 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010210}
10211
10212/**
10213 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10214 * do not receive key events.
10215 */
10216TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010217 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010218 spy->setFocusable(false);
10219
10220 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010221 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010222 setFocusedWindow(window);
10223 window->consumeFocusEvent(true);
10224
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010226 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10227 window->consumeKeyDown(ADISPLAY_ID_NONE);
10228
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010230 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10231 window->consumeKeyUp(ADISPLAY_ID_NONE);
10232
10233 spy->assertNoEvents();
10234}
10235
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010236using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10237
10238/**
10239 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10240 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10241 */
10242TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10243 auto window = createForeground();
10244 auto spy1 = createSpy();
10245 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010246 mDispatcher->onWindowInfosChanged(
10247 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010248
10249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010250 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010251 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10252 window->consumeMotionDown();
10253 spy1->consumeMotionDown();
10254 spy2->consumeMotionDown();
10255
10256 // Pilfer pointers from the second spy window.
10257 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10258 spy2->assertNoEvents();
10259 spy1->consumeMotionCancel();
10260 window->consumeMotionCancel();
10261
10262 // The rest of the gesture should only be sent to the second spy window.
10263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010264 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010265 ADISPLAY_ID_DEFAULT))
10266 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10267 spy2->consumeMotionMove();
10268 spy1->assertNoEvents();
10269 window->assertNoEvents();
10270}
10271
10272/**
10273 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10274 * in the middle of the gesture.
10275 */
10276TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10277 auto window = createForeground();
10278 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010279 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010280
10281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010282 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10284 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10285 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10286
10287 window->releaseChannel();
10288
10289 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10290
10291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010292 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10294 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10295}
10296
10297/**
10298 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10299 * the spy, but not to any other windows.
10300 */
10301TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10302 auto spy = createSpy();
10303 auto window = createForeground();
10304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010305 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010306
10307 // First finger down on the window and the spy.
10308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010309 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010310 {100, 200}))
10311 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10312 spy->consumeMotionDown();
10313 window->consumeMotionDown();
10314
10315 // Spy window pilfers the pointers.
10316 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10317 window->consumeMotionCancel();
10318
10319 // Second finger down on the window and spy, but the window should not receive the pointer down.
10320 const MotionEvent secondFingerDownEvent =
10321 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10322 .displayId(ADISPLAY_ID_DEFAULT)
10323 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010324 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10325 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010326 .build();
10327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010328 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010329 InputEventInjectionSync::WAIT_FOR_RESULT))
10330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10331
Harry Cutts33476232023-01-30 19:57:29 +000010332 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010333
10334 // Third finger goes down outside all windows, so injection should fail.
10335 const MotionEvent thirdFingerDownEvent =
10336 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10337 .displayId(ADISPLAY_ID_DEFAULT)
10338 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010339 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10340 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10341 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010342 .build();
10343 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010344 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010345 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010346 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010347
10348 spy->assertNoEvents();
10349 window->assertNoEvents();
10350}
10351
10352/**
10353 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10354 */
10355TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10356 auto spy = createSpy();
10357 spy->setFrame(Rect(0, 0, 100, 100));
10358 auto window = createForeground();
10359 window->setFrame(Rect(0, 0, 200, 200));
10360
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010361 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010362
10363 // First finger down on the window only
10364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010365 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010366 {150, 150}))
10367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10368 window->consumeMotionDown();
10369
10370 // Second finger down on the spy and window
10371 const MotionEvent secondFingerDownEvent =
10372 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10373 .displayId(ADISPLAY_ID_DEFAULT)
10374 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010375 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10376 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010377 .build();
10378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010379 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010380 InputEventInjectionSync::WAIT_FOR_RESULT))
10381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10382 spy->consumeMotionDown();
10383 window->consumeMotionPointerDown(1);
10384
10385 // Third finger down on the spy and window
10386 const MotionEvent thirdFingerDownEvent =
10387 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10388 .displayId(ADISPLAY_ID_DEFAULT)
10389 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010390 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10391 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10392 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010393 .build();
10394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010395 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010396 InputEventInjectionSync::WAIT_FOR_RESULT))
10397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10398 spy->consumeMotionPointerDown(1);
10399 window->consumeMotionPointerDown(2);
10400
10401 // Spy window pilfers the pointers.
10402 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010403 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10404 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010405
10406 spy->assertNoEvents();
10407 window->assertNoEvents();
10408}
10409
10410/**
10411 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10412 * other windows should be canceled. If this results in the cancellation of all pointers for some
10413 * window, then that window should receive ACTION_CANCEL.
10414 */
10415TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10416 auto spy = createSpy();
10417 spy->setFrame(Rect(0, 0, 100, 100));
10418 auto window = createForeground();
10419 window->setFrame(Rect(0, 0, 200, 200));
10420
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010421 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010422
10423 // First finger down on both spy and window
10424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010425 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010426 {10, 10}))
10427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10428 window->consumeMotionDown();
10429 spy->consumeMotionDown();
10430
10431 // Second finger down on the spy and window
10432 const MotionEvent secondFingerDownEvent =
10433 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10434 .displayId(ADISPLAY_ID_DEFAULT)
10435 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010436 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10437 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010438 .build();
10439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010440 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010441 InputEventInjectionSync::WAIT_FOR_RESULT))
10442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10443 spy->consumeMotionPointerDown(1);
10444 window->consumeMotionPointerDown(1);
10445
10446 // Spy window pilfers the pointers.
10447 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10448 window->consumeMotionCancel();
10449
10450 spy->assertNoEvents();
10451 window->assertNoEvents();
10452}
10453
10454/**
10455 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10456 * be sent to other windows
10457 */
10458TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10459 auto spy = createSpy();
10460 spy->setFrame(Rect(0, 0, 100, 100));
10461 auto window = createForeground();
10462 window->setFrame(Rect(0, 0, 200, 200));
10463
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010464 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010465
10466 // First finger down on both window and spy
10467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010468 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010469 {10, 10}))
10470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10471 window->consumeMotionDown();
10472 spy->consumeMotionDown();
10473
10474 // Spy window pilfers the pointers.
10475 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10476 window->consumeMotionCancel();
10477
10478 // Second finger down on the window only
10479 const MotionEvent secondFingerDownEvent =
10480 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10481 .displayId(ADISPLAY_ID_DEFAULT)
10482 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010483 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10484 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010485 .build();
10486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010487 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010488 InputEventInjectionSync::WAIT_FOR_RESULT))
10489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10490 window->consumeMotionDown();
10491 window->assertNoEvents();
10492
10493 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10494 spy->consumeMotionMove();
10495 spy->assertNoEvents();
10496}
10497
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010498/**
10499 * A window on the left and a window on the right. Also, a spy window that's above all of the
10500 * windows, and spanning both left and right windows.
10501 * Send simultaneous motion streams from two different devices, one to the left window, and another
10502 * to the right window.
10503 * Pilfer from spy window.
10504 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10505 */
10506TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10507 sp<FakeWindowHandle> spy = createSpy();
10508 spy->setFrame(Rect(0, 0, 200, 200));
10509 sp<FakeWindowHandle> leftWindow = createForeground();
10510 leftWindow->setFrame(Rect(0, 0, 100, 100));
10511
10512 sp<FakeWindowHandle> rightWindow = createForeground();
10513 rightWindow->setFrame(Rect(100, 0, 200, 100));
10514
10515 constexpr int32_t stylusDeviceId = 1;
10516 constexpr int32_t touchDeviceId = 2;
10517
10518 mDispatcher->onWindowInfosChanged(
10519 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10520
10521 // Stylus down on left window and spy
10522 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10523 .deviceId(stylusDeviceId)
10524 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10525 .build());
10526 leftWindow->consumeMotionEvent(
10527 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10528 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10529
10530 // Finger down on right window and spy - but spy already has stylus
10531 mDispatcher->notifyMotion(
10532 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10533 .deviceId(touchDeviceId)
10534 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10535 .build());
10536 rightWindow->consumeMotionEvent(
10537 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010538 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010539
10540 // Act: pilfer from spy. Spy is currently receiving touch events.
10541 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010542 leftWindow->consumeMotionEvent(
10543 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010544 rightWindow->consumeMotionEvent(
10545 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10546
10547 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10548 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10549 .deviceId(stylusDeviceId)
10550 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10551 .build());
10552 mDispatcher->notifyMotion(
10553 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10554 .deviceId(touchDeviceId)
10555 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10556 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010557 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010558
10559 spy->assertNoEvents();
10560 leftWindow->assertNoEvents();
10561 rightWindow->assertNoEvents();
10562}
10563
Prabir Pradhand65552b2021-10-07 11:23:50 -070010564class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10565public:
10566 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10567 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10568 std::make_shared<FakeApplicationHandle>();
10569 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010570 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10571 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010572 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010573 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010574 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010575 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010576 overlay->setTrustedOverlay(true);
10577
10578 std::shared_ptr<FakeApplicationHandle> application =
10579 std::make_shared<FakeApplicationHandle>();
10580 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010581 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10582 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010583 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010584 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010585
10586 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010587 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010588 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010589 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010590 return {std::move(overlay), std::move(window)};
10591 }
10592
10593 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010594 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010595 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010596 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010597 }
10598
10599 void sendStylusEvent(int32_t action) {
10600 NotifyMotionArgs motionArgs =
10601 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10602 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010603 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010604 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010605 }
10606};
10607
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010608using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10609
10610TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010611 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010612 ScopedSilentDeath _silentDeath;
10613
Prabir Pradhand65552b2021-10-07 11:23:50 -070010614 auto [overlay, window] = setupStylusOverlayScenario();
10615 overlay->setTrustedOverlay(false);
10616 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010617 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10618 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010619 ".* not a trusted overlay");
10620}
10621
10622TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10623 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010624 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010625
10626 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10627 overlay->consumeMotionDown();
10628 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10629 overlay->consumeMotionUp();
10630
10631 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10632 window->consumeMotionDown();
10633 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10634 window->consumeMotionUp();
10635
10636 overlay->assertNoEvents();
10637 window->assertNoEvents();
10638}
10639
10640TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10641 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010642 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010643 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010644
10645 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10646 overlay->consumeMotionDown();
10647 window->consumeMotionDown();
10648 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10649 overlay->consumeMotionUp();
10650 window->consumeMotionUp();
10651
10652 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10653 window->consumeMotionDown();
10654 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10655 window->consumeMotionUp();
10656
10657 overlay->assertNoEvents();
10658 window->assertNoEvents();
10659}
10660
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010661/**
10662 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10663 * The scenario is as follows:
10664 * - The stylus interceptor overlay is configured as a spy window.
10665 * - The stylus interceptor spy receives the start of a new stylus gesture.
10666 * - It pilfers pointers and then configures itself to no longer be a spy.
10667 * - The stylus interceptor continues to receive the rest of the gesture.
10668 */
10669TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10670 auto [overlay, window] = setupStylusOverlayScenario();
10671 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010672 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010673
10674 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10675 overlay->consumeMotionDown();
10676 window->consumeMotionDown();
10677
10678 // The interceptor pilfers the pointers.
10679 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10680 window->consumeMotionCancel();
10681
10682 // The interceptor configures itself so that it is no longer a spy.
10683 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010684 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010685
10686 // It continues to receive the rest of the stylus gesture.
10687 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10688 overlay->consumeMotionMove();
10689 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10690 overlay->consumeMotionUp();
10691
10692 window->assertNoEvents();
10693}
10694
Prabir Pradhan5735a322022-04-11 17:23:34 +000010695struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010696 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010697 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010698 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10699 std::unique_ptr<InputDispatcher>& mDispatcher;
10700
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010701 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010702 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10703
10704 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010705 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010706 ADISPLAY_ID_DEFAULT, {100, 200},
10707 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10708 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10709 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10710 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10711 }
10712
10713 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010714 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010715 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010716 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010717 mPolicyFlags);
10718 }
10719
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010720 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010721 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10722 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010723 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10724 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010725 window->setOwnerInfo(mPid, mUid);
10726 return window;
10727 }
10728};
10729
10730using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10731
10732TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010733 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010734 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010735 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010736
10737 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10738 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10739 window->consumeMotionDown();
10740
10741 setFocusedWindow(window);
10742 window->consumeFocusEvent(true);
10743
10744 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10745 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10746 window->consumeKeyDown(ADISPLAY_ID_NONE);
10747}
10748
10749TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010750 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010751 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010753
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010754 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010755 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10756 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10757
10758 setFocusedWindow(window);
10759 window->consumeFocusEvent(true);
10760
10761 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10762 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10763 window->assertNoEvents();
10764}
10765
10766TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010767 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010768 auto window = owner.createWindow("Owned window");
10769 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010770 spy->setSpy(true);
10771 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010772 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010773
10774 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10775 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10776 spy->consumeMotionDown();
10777 window->consumeMotionDown();
10778}
10779
10780TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010781 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010782 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010783
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010784 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010785 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010786 randosSpy->setSpy(true);
10787 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010788 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010789
10790 // The event is targeted at owner's window, so injection should succeed, but the spy should
10791 // not receive the event.
10792 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10793 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10794 randosSpy->assertNoEvents();
10795 window->consumeMotionDown();
10796}
10797
10798TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010799 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010800 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010801
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010802 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010803 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010804 randosSpy->setSpy(true);
10805 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010806 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010807
10808 // A user that has injection permission can inject into any window.
10809 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010810 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010811 ADISPLAY_ID_DEFAULT));
10812 randosSpy->consumeMotionDown();
10813 window->consumeMotionDown();
10814
10815 setFocusedWindow(randosSpy);
10816 randosSpy->consumeFocusEvent(true);
10817
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010818 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010819 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10820 window->assertNoEvents();
10821}
10822
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010823TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010824 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010825 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010826
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010827 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010828 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010829 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10830 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010831 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010832
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010833 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010834 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10835 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10836 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010837 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010838}
10839
Garfield Tane84e6f92019-08-29 17:28:41 -070010840} // namespace android::inputdispatcher