blob: 71362e3be97afd4231aa832fe7139c93eca9b494 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070023#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080024#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080025#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070026#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070027#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000028#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000029#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000030#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080031#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080032#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100033#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070034#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080036#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100037
Garfield Tan1c7bc862020-01-28 13:24:04 -080038#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080039#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070040#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080041#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080042#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080043
Garfield Tan1c7bc862020-01-28 13:24:04 -080044using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050045using android::gui::FocusRequest;
46using android::gui::TouchOcclusionMode;
47using android::gui::WindowInfo;
48using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080049using android::os::InputEventInjectionResult;
50using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080051
Garfield Tane84e6f92019-08-29 17:28:41 -070052namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080053
Dominik Laskowski2f01d772022-03-23 16:01:29 -070054using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080055using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070056
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070057namespace {
58
Michael Wrightd02c5b62014-02-10 15:10:22 -080059// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000060static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080061
62// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000063static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080064static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080065
Jeff Brownf086ddb2014-02-11 14:28:48 -080066// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000067static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
68static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080069
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000070// Ensure common actions are interchangeable between keys and motions for convenience.
71static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
72static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080073static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
74static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
75static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
76static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070077static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080078static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070079static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080080static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080081static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080082/**
83 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
84 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
85 * index 0) is the new pointer going down. The same pointer could have been placed at a different
86 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
87 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
88 * pointer id=0 leaves but the pointer id=1 remains.
89 */
90static constexpr int32_t POINTER_0_DOWN =
91 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000094static constexpr int32_t POINTER_2_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000096static constexpr int32_t POINTER_3_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000098static constexpr int32_t POINTER_0_UP =
99 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100static constexpr int32_t POINTER_1_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000102static constexpr int32_t POINTER_2_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800104
Antonio Kantek15beb512022-06-13 22:35:41 +0000105// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000106static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000107static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000108
Antonio Kantek15beb512022-06-13 22:35:41 +0000109// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000110static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000111static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000112
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000113// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700116/**
117 * If we expect to receive the event, the timeout can be made very long. When the test are running
118 * correctly, we will actually never wait until the end of the timeout because the wait will end
119 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
120 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
121 * developer can see the failure quickly (on human scale).
122 */
123static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
124/**
125 * When no event is expected, we can have a very short timeout. A large value here would slow down
126 * the tests. In the unlikely event of system being too slow, the event may still be present but the
127 * timeout would complete before it is consumed. This would result in test flakiness. If this
128 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
129 * would get noticed and addressed quickly.
130 */
131static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
132
Arthur Hungc539dbb2022-12-08 07:45:36 +0000133static constexpr int expectedWallpaperFlags =
134 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
135
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800136using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
137
Gang Wang342c9272020-01-13 13:15:04 -0500138/**
139 * Return a DOWN key event with KEYCODE_A.
140 */
141static KeyEvent getTestKeyEvent() {
142 KeyEvent event;
143
Garfield Tanfbe732e2020-01-24 11:26:14 -0800144 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
145 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
146 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500147 return event;
148}
149
Michael Wrightd02c5b62014-02-10 15:10:22 -0800150// --- FakeInputDispatcherPolicy ---
151
152class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000153 struct AnrResult {
154 sp<IBinder> token{};
155 gui::Pid pid{gui::Pid::INVALID};
156 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800157
Michael Wrightd02c5b62014-02-10 15:10:22 -0800158public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000159 FakeInputDispatcherPolicy() = default;
160 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800161
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800162 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700163 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700164 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 EXPECT_EQ(event.getDisplayId(), args.displayId);
166
167 const auto& keyEvent = static_cast<const KeyEvent&>(event);
168 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
169 EXPECT_EQ(keyEvent.getAction(), args.action);
170 });
Jackal Guof9696682018-10-05 12:23:23 +0800171 }
172
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700173 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
174 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700175 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700176 EXPECT_EQ(event.getDisplayId(), args.displayId);
177
178 const auto& motionEvent = static_cast<const MotionEvent&>(event);
179 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
180 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000181 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
182 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
183 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700185 });
Jackal Guof9696682018-10-05 12:23:23 +0800186 }
187
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700188 void assertFilterInputEventWasNotCalled() {
189 std::scoped_lock lock(mLock);
190 ASSERT_EQ(nullptr, mFilteredEvent);
191 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800192
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800193 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700194 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 ASSERT_TRUE(mConfigurationChangedTime)
196 << "Timed out waiting for configuration changed call";
197 ASSERT_EQ(*mConfigurationChangedTime, when);
198 mConfigurationChangedTime = std::nullopt;
199 }
200
201 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700202 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800203 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800204 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
206 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
207 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
208 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
209 mLastNotifySwitch = std::nullopt;
210 }
211
chaviwfd6d3512019-03-25 13:23:49 -0700212 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700213 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800214 ASSERT_EQ(touchedToken, mOnPointerDownToken);
215 mOnPointerDownToken.clear();
216 }
217
218 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700219 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800220 ASSERT_TRUE(mOnPointerDownToken == nullptr)
221 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700222 }
223
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700224 // This function must be called soon after the expected ANR timer starts,
225 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500226 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700227 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800229 std::unique_lock lock(mLock);
230 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500231 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800232 ASSERT_NO_FATAL_FAILURE(
233 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500234 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700235 }
236
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000237 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800238 const sp<WindowInfoHandle>& window) {
239 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
240 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
241 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500242 }
243
Prabir Pradhanedd96402022-02-15 01:46:16 -0800244 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
245 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000246 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800247 std::unique_lock lock(mLock);
248 android::base::ScopedLockAssertion assumeLocked(mLock);
249 AnrResult result;
250 ASSERT_NO_FATAL_FAILURE(result =
251 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000252 ASSERT_EQ(expectedToken, result.token);
253 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500254 }
255
Prabir Pradhanedd96402022-02-15 01:46:16 -0800256 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000257 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500258 std::unique_lock lock(mLock);
259 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800260 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
261 const auto& [token, _] = result;
262 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000263 }
264
Prabir Pradhanedd96402022-02-15 01:46:16 -0800265 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000266 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 std::unique_lock lock(mLock);
268 android::base::ScopedLockAssertion assumeLocked(mLock);
269 AnrResult result;
270 ASSERT_NO_FATAL_FAILURE(
271 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000272 ASSERT_EQ(expectedToken, result.token);
273 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800274 }
275
276 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000277 sp<IBinder> getResponsiveWindowToken() {
278 std::unique_lock lock(mLock);
279 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800280 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
281 const auto& [token, _] = result;
282 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700283 }
284
285 void assertNotifyAnrWasNotCalled() {
286 std::scoped_lock lock(mLock);
287 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 ASSERT_TRUE(mAnrWindows.empty());
289 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500290 << "ANR was not called, but please also consume the 'connection is responsive' "
291 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700292 }
293
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000294 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800295 std::unique_lock lock(mLock);
296 base::ScopedLockAssertion assumeLocked(mLock);
297
298 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
299 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000300 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800301 enabled;
302 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000303 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
304 << ") to be called.";
305 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800306 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000307 auto request = *mPointerCaptureRequest;
308 mPointerCaptureRequest.reset();
309 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800310 }
311
312 void assertSetPointerCaptureNotCalled() {
313 std::unique_lock lock(mLock);
314 base::ScopedLockAssertion assumeLocked(mLock);
315
316 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000317 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800318 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
323
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700324 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
325 const sp<IBinder>& targetToken) {
326 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800327 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800328 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800329 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800331 }
332
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800333 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
334 std::unique_lock lock(mLock);
335 base::ScopedLockAssertion assumeLocked(mLock);
336 std::optional<sp<IBinder>> receivedToken =
337 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
338 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000339 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800340 ASSERT_EQ(token, *receivedToken);
341 }
342
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800343 /**
344 * Set policy timeout. A value of zero means next key will not be intercepted.
345 */
346 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
347 mInterceptKeyTimeout = timeout;
348 }
349
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700350 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
351
Josep del Riob3981622023-04-18 15:49:45 +0000352 void assertUserActivityPoked() {
353 std::scoped_lock lock(mLock);
354 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
355 }
356
357 void assertUserActivityNotPoked() {
358 std::scoped_lock lock(mLock);
359 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
360 }
361
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000362 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000363 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
364 }
365
366 void assertNotifyDeviceInteractionWasNotCalled() {
367 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
368 }
369
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000370 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
371 std::scoped_lock lock(mLock);
372 mUnhandledKeyHandler = handler;
373 }
374
375 void assertUnhandledKeyReported(int32_t keycode) {
376 std::unique_lock lock(mLock);
377 base::ScopedLockAssertion assumeLocked(mLock);
378 std::optional<int32_t> unhandledKeycode =
379 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
380 mNotifyUnhandledKey);
381 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
382 ASSERT_EQ(unhandledKeycode, keycode);
383 }
384
385 void assertUnhandledKeyNotReported() {
386 std::unique_lock lock(mLock);
387 base::ScopedLockAssertion assumeLocked(mLock);
388 std::optional<int32_t> unhandledKeycode =
389 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
390 mNotifyUnhandledKey);
391 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
392 }
393
Michael Wrightd02c5b62014-02-10 15:10:22 -0800394private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700395 std::mutex mLock;
396 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
397 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
398 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
399 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800400
Prabir Pradhan99987712020-11-10 18:43:05 -0800401 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000402
403 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800404
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700405 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700406 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800407 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
408 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700409 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800410 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
411 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700412
arthurhungf452d0b2021-01-06 00:19:52 +0800413 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800414 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000415 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800416
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800417 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
418
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700419 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
420
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000421 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000422
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000423 std::condition_variable mNotifyUnhandledKey;
424 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
425 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
426
Prabir Pradhanedd96402022-02-15 01:46:16 -0800427 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
428 // for a specific container to become non-empty. When the container is non-empty, return the
429 // first entry from the container and erase it.
430 template <class T>
431 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
432 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
433 // If there is an ANR, Dispatcher won't be idle because there are still events
434 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
435 // before checking if ANR was called.
436 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
437 // to provide it some time to act. 100ms seems reasonable.
438 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
439 const std::chrono::time_point start = std::chrono::steady_clock::now();
440 std::optional<T> token =
441 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
442 if (!token.has_value()) {
443 ADD_FAILURE() << "Did not receive the ANR callback";
444 return {};
445 }
446
447 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
448 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
449 // the dispatcher started counting before this function was called
450 if (std::chrono::abs(timeout - waited) > 100ms) {
451 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
452 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
453 << "ms, but waited "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
455 << "ms instead";
456 }
457 return *token;
458 }
459
460 template <class T>
461 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
462 std::queue<T>& storage,
463 std::unique_lock<std::mutex>& lock,
464 std::condition_variable& condition)
465 REQUIRES(mLock) {
466 condition.wait_for(lock, timeout,
467 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
468 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800469 return std::nullopt;
470 }
471 T item = storage.front();
472 storage.pop();
473 return std::make_optional(item);
474 }
475
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600476 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700477 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800478 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800479 }
480
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000481 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800482 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700483 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 ASSERT_TRUE(pid.has_value());
485 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700486 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500487 }
488
Prabir Pradhanedd96402022-02-15 01:46:16 -0800489 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000490 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500491 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800492 ASSERT_TRUE(pid.has_value());
493 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500494 mNotifyAnr.notify_all();
495 }
496
497 void notifyNoFocusedWindowAnr(
498 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
499 std::scoped_lock lock(mLock);
500 mAnrApplications.push(applicationHandle);
501 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800502 }
503
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800504 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
505 std::scoped_lock lock(mLock);
506 mBrokenInputChannels.push(connectionToken);
507 mNotifyInputChannelBroken.notify_all();
508 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800509
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600510 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700511
Chris Yef59a2f42020-10-16 12:55:26 -0700512 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
513 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
514 const std::vector<float>& values) override {}
515
516 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
517 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000518
Chris Yefb552902021-02-03 17:18:37 -0800519 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
520
Prabir Pradhana41d2442023-04-20 21:30:40 +0000521 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700522 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700524 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
526 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800527 break;
528 }
529
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700530 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000531 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
532 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800533 break;
534 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700535 default: {
536 ADD_FAILURE() << "Should only filter keys or motions";
537 break;
538 }
Jackal Guof9696682018-10-05 12:23:23 +0800539 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800540 return true;
541 }
542
Prabir Pradhana41d2442023-04-20 21:30:40 +0000543 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
544 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800545 // Clear intercept state when we handled the event.
546 mInterceptKeyTimeout = 0ms;
547 }
548 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800549
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600550 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Prabir Pradhana41d2442023-04-20 21:30:40 +0000552 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800553 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
554 // Clear intercept state so we could dispatch the event in next wake.
555 mInterceptKeyTimeout = 0ms;
556 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800557 }
558
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000559 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000560 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::scoped_lock lock(mLock);
562 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
563 mNotifyUnhandledKey.notify_all();
564 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565 }
566
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600567 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
568 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700569 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800570 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
571 * essentially a passthrough for notifySwitch.
572 */
Harry Cutts33476232023-01-30 19:57:29 +0000573 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574 }
575
Josep del Riob3981622023-04-18 15:49:45 +0000576 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
577 std::scoped_lock lock(mLock);
578 mPokedUserActivity = true;
579 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700581 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
582 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
583 }
584
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600585 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700586 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700587 mOnPointerDownToken = newToken;
588 }
589
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000590 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800591 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000592 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800593 mPointerCaptureChangedCondition.notify_all();
594 }
595
arthurhungf452d0b2021-01-06 00:19:52 +0800596 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
597 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800598 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800599 mDropTargetWindowToken = token;
600 }
601
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000602 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000603 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000604 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
605 }
606
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700607 void assertFilterInputEventWasCalledInternal(
608 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700609 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800610 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700611 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800612 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800613 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700615} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617// --- InputDispatcherTest ---
618
619class InputDispatcherTest : public testing::Test {
620protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000621 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700622 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000624 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000625 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700626 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
627
Harry Cutts101ee9b2023-07-06 18:04:14 +0000628 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000629 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700630 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800631 }
632
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000633 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700634 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000635 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700636 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800637 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700638
639 /**
640 * Used for debugging when writing the test
641 */
642 void dumpDispatcherState() {
643 std::string dump;
644 mDispatcher->dump(dump);
645 std::stringstream ss(dump);
646 std::string to;
647
648 while (std::getline(ss, to, '\n')) {
649 ALOGE("%s", to.c_str());
650 }
651 }
Vishnu Nair958da932020-08-21 17:12:37 -0700652
Chavi Weingarten847e8512023-03-29 00:26:09 +0000653 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700654 FocusRequest request;
655 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000656 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700657 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
658 request.displayId = window->getInfo()->displayId;
659 mDispatcher->setFocusedWindow(request);
660 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800661};
662
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
664 KeyEvent event;
665
666 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800667 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
668 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000669 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600670 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800671 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000672 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000673 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800674 << "Should reject key events with undefined action.";
675
676 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800677 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
678 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600679 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800680 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000681 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000682 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800683 << "Should reject key events with ACTION_MULTIPLE.";
684}
685
686TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
687 MotionEvent event;
688 PointerProperties pointerProperties[MAX_POINTERS + 1];
689 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800690 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800691 pointerProperties[i].clear();
692 pointerProperties[i].id = i;
693 pointerCoords[i].clear();
694 }
695
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800696 // Some constants commonly used below
697 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
698 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
699 constexpr int32_t metaState = AMETA_NONE;
700 constexpr MotionClassification classification = MotionClassification::NONE;
701
chaviw9eaa22c2020-07-01 16:21:27 -0700702 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800703 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800704 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000705 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700706 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700707 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
708 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000709 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800710 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000711 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000712 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800713 << "Should reject motion events with undefined action.";
714
715 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800716 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800717 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
718 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
719 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
720 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800722 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000723 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000724 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800725 << "Should reject motion events with pointer down index too large.";
726
Garfield Tanfbe732e2020-01-24 11:26:14 -0800727 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700728 AMOTION_EVENT_ACTION_POINTER_DOWN |
729 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700730 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
731 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700732 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000733 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800734 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000735 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000736 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800737 << "Should reject motion events with pointer down index too small.";
738
739 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800740 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800741 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
742 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
743 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
744 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000745 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800746 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000747 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000748 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800749 << "Should reject motion events with pointer up index too large.";
750
Garfield Tanfbe732e2020-01-24 11:26:14 -0800751 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700752 AMOTION_EVENT_ACTION_POINTER_UP |
753 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700754 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
755 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700756 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000757 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800758 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000759 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000760 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800761 << "Should reject motion events with pointer up index too small.";
762
763 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800764 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
765 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700766 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700767 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
768 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000769 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000771 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000772 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800773 << "Should reject motion events with 0 pointers.";
774
Garfield Tanfbe732e2020-01-24 11:26:14 -0800775 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
776 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700777 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700778 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
779 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000780 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800781 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000782 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000783 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800784 << "Should reject motion events with more than MAX_POINTERS pointers.";
785
786 // Rejects motion events with invalid pointer ids.
787 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800788 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
789 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700790 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700791 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
792 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000793 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800794 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000795 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000796 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800797 << "Should reject motion events with pointer ids less than 0.";
798
799 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800800 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
801 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700802 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700803 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
804 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000805 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800806 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000807 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000808 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800809 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
810
811 // Rejects motion events with duplicate pointer ids.
812 pointerProperties[0].id = 1;
813 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800814 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
815 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700816 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700817 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
818 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000819 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800820 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000821 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000822 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800823 << "Should reject motion events with duplicate pointer ids.";
824}
825
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800826/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
827
828TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
829 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000830 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800831 ASSERT_TRUE(mDispatcher->waitForIdle());
832
833 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
834}
835
836TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000837 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
838 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000839 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800840
841 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
842 args.policyFlags |= POLICY_FLAG_TRUSTED;
843 mFakePolicy->assertNotifySwitchWasCalled(args);
844}
845
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700846namespace {
847
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700848static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700849// Default input dispatching timeout if there is no focused application or paused window
850// from which to determine an appropriate dispatching timeout.
851static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
852 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
853 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800854
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800855class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800856public:
Garfield Tan15601662020-09-22 15:32:38 -0700857 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700858 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800859
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000860 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700861 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700862 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700863 if (!consumeSeq) {
864 return nullptr;
865 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000866 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867 return event;
868 }
869
870 /**
871 * Receive an event without acknowledging it.
872 * Return the sequence number that could later be used to send finished signal.
873 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700874 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
875 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800876 uint32_t consumeSeq;
877 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800878
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800879 std::chrono::time_point start = std::chrono::steady_clock::now();
880 status_t status = WOULD_BLOCK;
881 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700882 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
883 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800884 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700885 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 break;
887 }
888 }
889
890 if (status == WOULD_BLOCK) {
891 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700892 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800893 }
894
895 if (status != OK) {
896 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800898 }
899 if (event == nullptr) {
900 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700901 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700903 if (outEvent != nullptr) {
904 *outEvent = event;
905 }
906 return consumeSeq;
907 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800908
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700909 /**
910 * To be used together with "receiveEvent" to complete the consumption of an event.
911 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000912 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700913 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915 }
916
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000917 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700918 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000919 ASSERT_EQ(OK, status);
920 }
921
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700922 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000923 std::optional<int32_t> expectedDisplayId,
924 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700925 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800926
927 ASSERT_NE(nullptr, event) << mName.c_str()
928 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800929 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700930 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
931 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800932
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000933 if (expectedDisplayId.has_value()) {
934 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
935 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800936
Tiger Huang8664f8c2018-10-11 19:14:35 +0800937 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700938 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800939 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700940 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000941 if (expectedFlags.has_value()) {
942 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
943 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800944 break;
945 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700946 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800947 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700948 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000949 if (expectedFlags.has_value()) {
950 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
951 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800952 break;
953 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700954 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100955 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
956 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700957 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800958 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
959 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700960 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000961 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
962 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700963 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800964 FAIL() << "Use 'consumeDragEvent' for DRAG events";
965 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800966 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800967 }
968
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800969 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700970 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800971
972 if (event == nullptr) {
973 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
974 return nullptr;
975 }
976
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 if (event->getType() != InputEventType::MOTION) {
978 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800979 return nullptr;
980 }
981 return static_cast<MotionEvent*>(event);
982 }
983
984 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
985 MotionEvent* motionEvent = consumeMotion();
986 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
987 ASSERT_THAT(*motionEvent, matcher);
988 }
989
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700991 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100992 ASSERT_NE(nullptr, event) << mName.c_str()
993 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700994 ASSERT_EQ(InputEventType::FOCUS, event->getType())
995 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100996
997 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
998 << mName.c_str() << ": event displayId should always be NONE.";
999
1000 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1001 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001002 }
1003
Prabir Pradhan99987712020-11-10 18:43:05 -08001004 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001005 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001006 ASSERT_NE(nullptr, event) << mName.c_str()
1007 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001008 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1009 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001010
1011 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1012 << mName.c_str() << ": event displayId should always be NONE.";
1013
1014 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1015 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1016 }
1017
arthurhungb89ccb02020-12-30 16:19:01 +08001018 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001019 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001020 ASSERT_NE(nullptr, event) << mName.c_str()
1021 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001022 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001023
1024 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1025 << mName.c_str() << ": event displayId should always be NONE.";
1026
1027 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1028 EXPECT_EQ(isExiting, dragEvent.isExiting());
1029 EXPECT_EQ(x, dragEvent.getX());
1030 EXPECT_EQ(y, dragEvent.getY());
1031 }
1032
Antonio Kantekf16f2832021-09-28 04:39:20 +00001033 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001034 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001035 ASSERT_NE(nullptr, event) << mName.c_str()
1036 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001037 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1038 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001039
1040 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1041 << mName.c_str() << ": event displayId should always be NONE.";
1042 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1043 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1044 }
1045
chaviwd1c23182019-12-20 18:44:56 -08001046 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001047 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001048 if (event == nullptr) {
1049 return;
1050 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001051 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1053 ADD_FAILURE() << "Received key event "
1054 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001056 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1057 ADD_FAILURE() << "Received motion event "
1058 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001059 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001060 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1061 ADD_FAILURE() << "Received focus event, hasFocus = "
1062 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001063 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001064 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1065 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1066 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001067 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001068 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1069 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1070 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001071 }
1072 FAIL() << mName.c_str()
1073 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001074 }
1075
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001076 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080private:
1081 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001082 PreallocatedInputEventFactory mEventFactory;
1083
1084 std::string mName;
1085};
1086
chaviw3277faf2021-05-19 16:45:23 -05001087class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001088public:
1089 static const int32_t WIDTH = 600;
1090 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001091
Chris Yea209fde2020-07-22 13:54:51 -07001092 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001093 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001094 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001095 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001097 base::Result<std::unique_ptr<InputChannel>> channel =
1098 dispatcher->createInputChannel(name);
1099 token = (*channel)->getConnectionToken();
1100 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001101 }
1102
1103 inputApplicationHandle->updateInfo();
1104 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1105
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001106 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001107 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001108 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001109 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001110 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001111 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001112 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001113 mInfo.globalScaleFactor = 1.0;
1114 mInfo.touchableRegion.clear();
1115 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001116 mInfo.ownerPid = WINDOW_PID;
1117 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001118 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001119 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001120 }
1121
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001122 sp<FakeWindowHandle> clone(int32_t displayId) {
1123 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1124 handle->mInfo = mInfo;
1125 handle->mInfo.displayId = displayId;
1126 handle->mInfo.id = sId++;
1127 handle->mInputReceiver = mInputReceiver;
1128 return handle;
1129 }
1130
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001131 void setTouchable(bool touchable) {
1132 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1133 }
chaviwd1c23182019-12-20 18:44:56 -08001134
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001135 void setFocusable(bool focusable) {
1136 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1137 }
1138
1139 void setVisible(bool visible) {
1140 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1141 }
Vishnu Nair958da932020-08-21 17:12:37 -07001142
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001143 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 }
1146
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001147 void setPaused(bool paused) {
1148 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1149 }
1150
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001151 void setPreventSplitting(bool preventSplitting) {
1152 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001153 }
1154
1155 void setSlippery(bool slippery) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1157 }
1158
1159 void setWatchOutsideTouch(bool watchOutside) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1161 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001162
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001163 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1164
1165 void setInterceptsStylus(bool interceptsStylus) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1167 }
1168
1169 void setDropInput(bool dropInput) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1171 }
1172
1173 void setDropInputIfObscured(bool dropInputIfObscured) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1175 }
1176
1177 void setNoInputChannel(bool noInputChannel) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1179 }
1180
Josep del Riob3981622023-04-18 15:49:45 +00001181 void setDisableUserActivity(bool disableUserActivity) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1183 }
1184
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001185 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1186
chaviw3277faf2021-05-19 16:45:23 -05001187 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001188
Bernardo Rufino7393d172021-02-26 13:56:11 +00001189 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1190
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001191 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001192 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001193 mInfo.touchableRegion.clear();
1194 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001195
1196 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1197 ui::Transform translate;
1198 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1199 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001200 }
1201
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001202 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1203
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001204 void setIsWallpaper(bool isWallpaper) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1206 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001207
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001208 void setDupTouchToWallpaper(bool hasWallpaper) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1210 }
chaviwd1c23182019-12-20 18:44:56 -08001211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setTrustedOverlay(bool trustedOverlay) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1214 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001215
chaviw9eaa22c2020-07-01 16:21:27 -07001216 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1217 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1218 }
1219
1220 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001221
yunho.shinf4a80b82020-11-16 21:13:57 +09001222 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1223
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001224 KeyEvent* consumeKey(bool handled = true) {
1225 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001226 if (event == nullptr) {
1227 ADD_FAILURE() << "Consume failed : no event";
1228 return nullptr;
1229 }
1230 if (event->getType() != InputEventType::KEY) {
1231 ADD_FAILURE() << "Instead of key event, got " << *event;
1232 return nullptr;
1233 }
1234 return static_cast<KeyEvent*>(event);
1235 }
1236
1237 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1238 KeyEvent* keyEvent = consumeKey();
1239 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1240 ASSERT_THAT(*keyEvent, matcher);
1241 }
1242
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001243 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001244 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 }
1246
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001247 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001248 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001249 }
1250
Svet Ganov5d3bc372020-01-26 23:11:07 -08001251 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001252 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001253 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1254 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 }
1256
1257 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001258 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001259 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1260 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 }
1262
1263 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001265 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1266 }
1267
1268 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1269 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001270 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001271 expectedFlags);
1272 }
1273
Svet Ganov5d3bc372020-01-26 23:11:07 -08001274 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001275 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1276 int32_t expectedFlags = 0) {
1277 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1278 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 }
1281
1282 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedFlags = 0) {
1284 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1285 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001286 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001287 }
1288
1289 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001290 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001291 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001292 expectedFlags);
1293 }
1294
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001295 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1296 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001297 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001298 expectedFlags);
1299 }
1300
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001301 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1302 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001303 MotionEvent* motionEvent = consumeMotion();
1304 ASSERT_NE(nullptr, motionEvent);
1305 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1306 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1307 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001308 }
1309
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001310 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1311 ASSERT_NE(mInputReceiver, nullptr)
1312 << "Cannot consume events from a window with no receiver";
1313 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1314 }
1315
Prabir Pradhan99987712020-11-10 18:43:05 -08001316 void consumeCaptureEvent(bool hasCapture) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeCaptureEvent(hasCapture);
1320 }
1321
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001322 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1323 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001324 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001325 ASSERT_THAT(*motionEvent, matcher);
1326 }
1327
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001328 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001329 std::optional<int32_t> expectedDisplayId,
1330 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001331 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1332 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1333 expectedFlags);
1334 }
1335
arthurhungb89ccb02020-12-30 16:19:01 +08001336 void consumeDragEvent(bool isExiting, float x, float y) {
1337 mInputReceiver->consumeDragEvent(isExiting, x, y);
1338 }
1339
Antonio Kantekf16f2832021-09-28 04:39:20 +00001340 void consumeTouchModeEvent(bool inTouchMode) {
1341 ASSERT_NE(mInputReceiver, nullptr)
1342 << "Cannot consume events from a window with no receiver";
1343 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1344 }
1345
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001346 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001347 if (mInputReceiver == nullptr) {
1348 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1349 return std::nullopt;
1350 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001351 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001352 }
1353
1354 void finishEvent(uint32_t sequenceNum) {
1355 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1356 mInputReceiver->finishEvent(sequenceNum);
1357 }
1358
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001359 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1360 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1361 mInputReceiver->sendTimeline(inputEventId, timeline);
1362 }
1363
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001364 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = true) {
chaviwaf87b3e2019-10-01 16:59:28 -07001365 if (mInputReceiver == nullptr) {
1366 return nullptr;
1367 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00001368 return mInputReceiver->consume(timeout, handled);
chaviwaf87b3e2019-10-01 16:59:28 -07001369 }
1370
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001371 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001372 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001373 if (event == nullptr) {
1374 ADD_FAILURE() << "Consume failed : no event";
1375 return nullptr;
1376 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001377 if (event->getType() != InputEventType::MOTION) {
1378 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001379 return nullptr;
1380 }
1381 return static_cast<MotionEvent*>(event);
1382 }
1383
Arthur Hungb92218b2018-08-14 12:00:21 +08001384 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001385 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001386 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001387 return; // Can't receive events if the window does not have input channel
1388 }
1389 ASSERT_NE(nullptr, mInputReceiver)
1390 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001391 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001392 }
1393
chaviwaf87b3e2019-10-01 16:59:28 -07001394 sp<IBinder> getToken() { return mInfo.token; }
1395
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001396 const std::string& getName() { return mName; }
1397
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001398 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001399 mInfo.ownerPid = ownerPid;
1400 mInfo.ownerUid = ownerUid;
1401 }
1402
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001403 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001404
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001405 void destroyReceiver() { mInputReceiver = nullptr; }
1406
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001407 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1408
chaviwd1c23182019-12-20 18:44:56 -08001409private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001410 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001411 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001412 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001413 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001414 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001415};
1416
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001417std::atomic<int32_t> FakeWindowHandle::sId{1};
1418
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001419class FakeMonitorReceiver {
1420public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001421 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1422 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001423
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001424 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001425
1426 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001427 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1428 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001429 }
1430
1431 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001432 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001433 }
1434
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001435 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001436
1437 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001438 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1439 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001440 }
1441
1442 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001443 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1444 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001445 }
1446
1447 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001448 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1449 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001450 }
1451
1452 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001453 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001454 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1455 WithDisplayId(expectedDisplayId),
1456 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1457 }
1458
1459 void consumeMotionPointerDown(int32_t pointerIdx) {
1460 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1461 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001462 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1463 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001464 }
1465
1466 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001467 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001468 }
1469
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001470 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001471
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001472 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001473
1474private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001475 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001476};
1477
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001478static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001479 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001480 int32_t displayId = ADISPLAY_ID_NONE,
1481 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001482 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001483 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001484 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001485 KeyEvent event;
1486 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1487
1488 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001489 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001490 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1491 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001492
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001493 if (!allowKeyRepeat) {
1494 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1495 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001496 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001497 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001498}
1499
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001500static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1501 InputEventInjectionResult result =
1502 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1503 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1504 if (result != InputEventInjectionResult::TIMED_OUT) {
1505 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1506 }
1507}
1508
1509static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001510 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001511 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001512}
1513
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001514// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1515// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1516// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001517static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1518 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001519 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001520 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001521 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001522}
1523
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001524static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001525 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001526 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001527}
1528
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001529static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001530 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001531 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001532 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001533 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001534 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1535 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001536}
1537
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001538static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001539 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1540 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001541 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001542 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1543 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001544 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001545 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001546 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001547 MotionEventBuilder motionBuilder =
1548 MotionEventBuilder(action, source)
1549 .displayId(displayId)
1550 .eventTime(eventTime)
1551 .rawXCursorPosition(cursorPosition.x)
1552 .rawYCursorPosition(cursorPosition.y)
1553 .pointer(
1554 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1555 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1556 motionBuilder.downTime(eventTime);
1557 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001558
1559 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001560 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1561 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001562}
1563
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001564static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1565 int32_t displayId,
1566 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001567 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001568}
1569
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001570static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1571 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001572 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001573 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001574}
1575
Jackal Guof9696682018-10-05 12:23:23 +08001576static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1577 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1578 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001579 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001580 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1581 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001582
1583 return args;
1584}
1585
Josep del Riob3981622023-04-18 15:49:45 +00001586static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1587 int32_t displayId = ADISPLAY_ID_NONE) {
1588 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1589 // Define a valid key event.
1590 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001591 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001592 currentTime);
1593
1594 return args;
1595}
1596
1597static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1598 int32_t displayId = ADISPLAY_ID_NONE) {
1599 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1600 // Define a valid key event.
1601 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001602 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001603 AMETA_NONE, currentTime);
1604
1605 return args;
1606}
1607
Prabir Pradhan678438e2023-04-13 19:32:51 +00001608[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1609 int32_t displayId,
1610 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001611 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001612 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1613 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1614 }
1615
chaviwd1c23182019-12-20 18:44:56 -08001616 PointerProperties pointerProperties[pointerCount];
1617 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001618
chaviwd1c23182019-12-20 18:44:56 -08001619 for (size_t i = 0; i < pointerCount; i++) {
1620 pointerProperties[i].clear();
1621 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001622 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001623
chaviwd1c23182019-12-20 18:44:56 -08001624 pointerCoords[i].clear();
1625 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1626 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1627 }
Jackal Guof9696682018-10-05 12:23:23 +08001628
1629 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1630 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001631 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001632 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1633 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001634 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001635 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001636 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001637 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001638
1639 return args;
1640}
1641
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001642static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1643 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1644}
1645
chaviwd1c23182019-12-20 18:44:56 -08001646static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1647 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1648}
1649
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001650static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1651 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001652 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001653}
1654
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001655} // namespace
1656
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001657/**
1658 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1659 * broken channel.
1660 */
1661TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1662 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1663 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001664 sp<FakeWindowHandle>::make(application, mDispatcher,
1665 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001666
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001667 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001668
1669 // Window closes its channel, but the window remains.
1670 window->destroyReceiver();
1671 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1672}
1673
Arthur Hungb92218b2018-08-14 12:00:21 +08001674TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001676 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1677 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001678
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001679 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001681 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001683
1684 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001685 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001686}
1687
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001688TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1691 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001692
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001693 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001694 // Inject a MotionEvent to an unknown display.
1695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001696 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1698
1699 // Window should receive motion event.
1700 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1701}
1702
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001704 * Calling onWindowInfosChanged once should not cause any issues.
1705 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706 * called twice.
1707 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001708TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001710 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1711 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001716 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719
1720 // Window should receive motion event.
1721 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1722}
1723
1724/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001725 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726 */
1727TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001729 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1730 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001731 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001732
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001733 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1734 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001736 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001737 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001739
1740 // Window should receive motion event.
1741 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1742}
1743
Arthur Hungb92218b2018-08-14 12:00:21 +08001744// The foreground window should receive the first touch down event.
1745TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001747 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001748 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001749 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001750 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001751
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001752 mDispatcher->onWindowInfosChanged(
1753 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001755 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001757
1758 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001759 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001760 windowSecond->assertNoEvents();
1761}
1762
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001763/**
1764 * Two windows: A top window, and a wallpaper behind the window.
1765 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1766 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001767 * 1. foregroundWindow <-- dup touch to wallpaper
1768 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001769 */
1770TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1772 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001773 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001774 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001775 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001776 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001777 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001778
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001779 mDispatcher->onWindowInfosChanged(
1780 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001782 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001783 {100, 200}))
1784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1785
1786 // Both foreground window and its wallpaper should receive the touch down
1787 foregroundWindow->consumeMotionDown();
1788 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1789
1790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001791 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001792 ADISPLAY_ID_DEFAULT, {110, 200}))
1793 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1794
1795 foregroundWindow->consumeMotionMove();
1796 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1797
1798 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001799 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001800 foregroundWindow->consumeMotionCancel();
1801 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1802 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1803}
1804
1805/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001806 * Two fingers down on the window, and lift off the first finger.
1807 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1808 * contains a single pointer.
1809 */
1810TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1812 sp<FakeWindowHandle> window =
1813 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1814
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001816 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1818 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1819 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001820 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001821 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1822 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1823 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1824 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001825 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001826 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1827 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1828 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1829 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001830 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1831 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1832 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1833
1834 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001835 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001836 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1837 window->consumeMotionEvent(
1838 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1839}
1840
1841/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001842 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1843 * with the following differences:
1844 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1845 * clean up the connection.
1846 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1847 * Ensure that there's no crash in the dispatcher.
1848 */
1849TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1851 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001852 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001853 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001854 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001855 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001856 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001857
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001858 mDispatcher->onWindowInfosChanged(
1859 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001861 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862 {100, 200}))
1863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1864
1865 // Both foreground window and its wallpaper should receive the touch down
1866 foregroundWindow->consumeMotionDown();
1867 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1868
1869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001870 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001871 ADISPLAY_ID_DEFAULT, {110, 200}))
1872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1873
1874 foregroundWindow->consumeMotionMove();
1875 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1876
1877 // Wallpaper closes its channel, but the window remains.
1878 wallpaperWindow->destroyReceiver();
1879 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1880
1881 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1882 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001883 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001884 foregroundWindow->consumeMotionCancel();
1885}
1886
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887class ShouldSplitTouchFixture : public InputDispatcherTest,
1888 public ::testing::WithParamInterface<bool> {};
1889INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1890 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001891/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001892 * A single window that receives touch (on top), and a wallpaper window underneath it.
1893 * The top window gets a multitouch gesture.
1894 * Ensure that wallpaper gets the same gesture.
1895 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001896TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001898 sp<FakeWindowHandle> foregroundWindow =
1899 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1900 foregroundWindow->setDupTouchToWallpaper(true);
1901 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902
1903 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001904 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001905 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001906
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001907 mDispatcher->onWindowInfosChanged(
1908 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909
1910 // Touch down on top window
1911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001912 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913 {100, 100}))
1914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1915
1916 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001917 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1919
1920 // Second finger down on the top window
1921 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001922 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001923 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001924 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1925 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001926 .build();
1927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001928 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001929 InputEventInjectionSync::WAIT_FOR_RESULT))
1930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1931
Harry Cutts33476232023-01-30 19:57:29 +00001932 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1933 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001935
1936 const MotionEvent secondFingerUpEvent =
1937 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1938 .displayId(ADISPLAY_ID_DEFAULT)
1939 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001940 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1941 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001942 .build();
1943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001944 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001945 InputEventInjectionSync::WAIT_FOR_RESULT))
1946 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1947 foregroundWindow->consumeMotionPointerUp(0);
1948 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1949
1950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001951 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001952 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1953 AINPUT_SOURCE_TOUCHSCREEN)
1954 .displayId(ADISPLAY_ID_DEFAULT)
1955 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001956 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001957 .x(100)
1958 .y(100))
1959 .build(),
1960 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1962 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1963 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964}
1965
1966/**
1967 * Two windows: a window on the left and window on the right.
1968 * A third window, wallpaper, is behind both windows, and spans both top windows.
1969 * The first touch down goes to the left window. A second pointer touches down on the right window.
1970 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1971 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1972 * ACTION_POINTER_DOWN(1).
1973 */
1974TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1975 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1976 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001977 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001979 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980
1981 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001982 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001983 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001984 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985
1986 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001987 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001989 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001991 mDispatcher->onWindowInfosChanged(
1992 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1993 {},
1994 0,
1995 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001996
1997 // Touch down on left window
1998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001999 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000 {100, 100}))
2001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2002
2003 // Both foreground window and its wallpaper should receive the touch down
2004 leftWindow->consumeMotionDown();
2005 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2006
2007 // Second finger down on the right window
2008 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002009 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002010 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002011 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2012 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002013 .build();
2014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002015 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002016 InputEventInjectionSync::WAIT_FOR_RESULT))
2017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2018
2019 leftWindow->consumeMotionMove();
2020 // Since the touch is split, right window gets ACTION_DOWN
2021 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002022 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023 expectedWallpaperFlags);
2024
2025 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002026 mDispatcher->onWindowInfosChanged(
2027 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002028 leftWindow->consumeMotionCancel();
2029 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2030 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2031
2032 // The pointer that's still down on the right window moves, and goes to the right window only.
2033 // As far as the dispatcher's concerned though, both pointers are still present.
2034 const MotionEvent secondFingerMoveEvent =
2035 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2036 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002037 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2038 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002039 .build();
2040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002041 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002042 InputEventInjectionSync::WAIT_FOR_RESULT));
2043 rightWindow->consumeMotionMove();
2044
2045 leftWindow->assertNoEvents();
2046 rightWindow->assertNoEvents();
2047 wallpaperWindow->assertNoEvents();
2048}
2049
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050/**
2051 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2052 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2053 * The right window should receive ACTION_DOWN.
2054 */
2055TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057 sp<FakeWindowHandle> leftWindow =
2058 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2059 leftWindow->setFrame(Rect(0, 0, 200, 200));
2060 leftWindow->setDupTouchToWallpaper(true);
2061 leftWindow->setSlippery(true);
2062
2063 sp<FakeWindowHandle> rightWindow =
2064 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2065 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002066
2067 sp<FakeWindowHandle> wallpaperWindow =
2068 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2069 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002070
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002071 mDispatcher->onWindowInfosChanged(
2072 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2073 {},
2074 0,
2075 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002076
Arthur Hungc539dbb2022-12-08 07:45:36 +00002077 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002079 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002080 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002082
2083 // Both foreground window and its wallpaper should receive the touch down
2084 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002085 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2086
Arthur Hungc539dbb2022-12-08 07:45:36 +00002087 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002089 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002090 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002091 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2092
Arthur Hungc539dbb2022-12-08 07:45:36 +00002093 leftWindow->consumeMotionCancel();
2094 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2095 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002096}
2097
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002098/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002099 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2100 * interactive, it might stop sending this flag.
2101 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2102 * to have a consistent input stream.
2103 *
2104 * Test procedure:
2105 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2106 * DOWN (new gesture).
2107 *
2108 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2109 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2110 *
2111 * We technically just need a single window here, but we are using two windows (spy on top and a
2112 * regular window below) to emulate the actual situation where it happens on the device.
2113 */
2114TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2116 sp<FakeWindowHandle> spyWindow =
2117 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2118 spyWindow->setFrame(Rect(0, 0, 200, 200));
2119 spyWindow->setTrustedOverlay(true);
2120 spyWindow->setSpy(true);
2121
2122 sp<FakeWindowHandle> window =
2123 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2124 window->setFrame(Rect(0, 0, 200, 200));
2125
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002126 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002128
2129 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002130 mDispatcher->notifyMotion(
2131 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2132 .deviceId(touchDeviceId)
2133 .policyFlags(DEFAULT_POLICY_FLAGS)
2134 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2135 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002136
Prabir Pradhan678438e2023-04-13 19:32:51 +00002137 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2138 .deviceId(touchDeviceId)
2139 .policyFlags(DEFAULT_POLICY_FLAGS)
2140 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2141 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2142 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002143 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2144 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2145 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2146 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2147
2148 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002149 mDispatcher->notifyMotion(
2150 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2151 .deviceId(touchDeviceId)
2152 .policyFlags(0)
2153 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2154 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2155 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002156 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2157 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2158
2159 // We don't need to reset the device to reproduce the issue, but the reset event typically
2160 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002161 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002162
2163 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002164 mDispatcher->notifyMotion(
2165 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2166 .deviceId(touchDeviceId)
2167 .policyFlags(DEFAULT_POLICY_FLAGS)
2168 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2169 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002170 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2171 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2172
2173 // No more events
2174 spyWindow->assertNoEvents();
2175 window->assertNoEvents();
2176}
2177
2178/**
Linnan Li907ae732023-09-05 17:14:21 +08002179 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2180 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2181 * interactive, it might stop sending this flag.
2182 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2183 * the consistency of the hover event in this case.
2184 *
2185 * Test procedure:
2186 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2187 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2188 *
2189 * We expect to receive two full streams of hover events.
2190 */
2191TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2193
2194 sp<FakeWindowHandle> window =
2195 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2196 window->setFrame(Rect(0, 0, 300, 300));
2197
2198 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2199
2200 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2201 .policyFlags(DEFAULT_POLICY_FLAGS)
2202 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2203 .build());
2204 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2205
2206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2207 .policyFlags(DEFAULT_POLICY_FLAGS)
2208 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2209 .build());
2210 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2211
2212 // Send hover exit without the default policy flags.
2213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2214 .policyFlags(0)
2215 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2216 .build());
2217
2218 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2219
2220 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2221 // right event.
2222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2223 .policyFlags(DEFAULT_POLICY_FLAGS)
2224 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2225 .build());
2226 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2227
2228 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2229 .policyFlags(DEFAULT_POLICY_FLAGS)
2230 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2231 .build());
2232 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2233
2234 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2235 .policyFlags(DEFAULT_POLICY_FLAGS)
2236 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2237 .build());
2238 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2239}
2240
2241/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002242 * Two windows: a window on the left and a window on the right.
2243 * Mouse is hovered from the right window into the left window.
2244 * Next, we tap on the left window, where the cursor was last seen.
2245 * The second tap is done onto the right window.
2246 * The mouse and tap are from two different devices.
2247 * We technically don't need to set the downtime / eventtime for these events, but setting these
2248 * explicitly helps during debugging.
2249 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2250 * In the buggy implementation, a tap on the right window would cause a crash.
2251 */
2252TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2253 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2254 sp<FakeWindowHandle> leftWindow =
2255 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2256 leftWindow->setFrame(Rect(0, 0, 200, 200));
2257
2258 sp<FakeWindowHandle> rightWindow =
2259 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2260 rightWindow->setFrame(Rect(200, 0, 400, 200));
2261
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002262 mDispatcher->onWindowInfosChanged(
2263 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002264 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2265 // stale.
2266 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2267 const int32_t mouseDeviceId = 6;
2268 const int32_t touchDeviceId = 4;
2269 // Move the cursor from right
2270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002271 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002272 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2273 AINPUT_SOURCE_MOUSE)
2274 .deviceId(mouseDeviceId)
2275 .downTime(baseTime + 10)
2276 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002277 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002278 .build()));
2279 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2280
2281 // .. to the left window
2282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002283 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002284 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2285 AINPUT_SOURCE_MOUSE)
2286 .deviceId(mouseDeviceId)
2287 .downTime(baseTime + 10)
2288 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002289 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002290 .build()));
2291 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2292 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2293 // Now tap the left window
2294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002295 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002296 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2297 AINPUT_SOURCE_TOUCHSCREEN)
2298 .deviceId(touchDeviceId)
2299 .downTime(baseTime + 40)
2300 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002301 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002302 .build()));
2303 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2304 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2305
2306 // release tap
2307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002309 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2310 AINPUT_SOURCE_TOUCHSCREEN)
2311 .deviceId(touchDeviceId)
2312 .downTime(baseTime + 40)
2313 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002314 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002315 .build()));
2316 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2317
2318 // Tap the window on the right
2319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002320 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002321 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2322 AINPUT_SOURCE_TOUCHSCREEN)
2323 .deviceId(touchDeviceId)
2324 .downTime(baseTime + 60)
2325 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002326 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002327 .build()));
2328 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2329
2330 // release tap
2331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002332 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002333 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2334 AINPUT_SOURCE_TOUCHSCREEN)
2335 .deviceId(touchDeviceId)
2336 .downTime(baseTime + 60)
2337 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002338 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002339 .build()));
2340 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2341
2342 // No more events
2343 leftWindow->assertNoEvents();
2344 rightWindow->assertNoEvents();
2345}
2346
2347/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002348 * Start hovering in a window. While this hover is still active, make another window appear on top.
2349 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2350 * While the top window is present, the hovering is stopped.
2351 * Later, hovering gets resumed again.
2352 * Ensure that new hover gesture is handled correctly.
2353 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2354 * to the window that's currently being hovered over.
2355 */
2356TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2357 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2358 sp<FakeWindowHandle> window =
2359 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2360 window->setFrame(Rect(0, 0, 200, 200));
2361
2362 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002364
2365 // Start hovering in the window
2366 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2367 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2368 .build());
2369 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2370
2371 // Now, an obscuring window appears!
2372 sp<FakeWindowHandle> obscuringWindow =
2373 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2374 ADISPLAY_ID_DEFAULT,
2375 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2376 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2377 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2378 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2379 obscuringWindow->setNoInputChannel(true);
2380 obscuringWindow->setFocusable(false);
2381 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002382 mDispatcher->onWindowInfosChanged(
2383 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002384
2385 // While this new obscuring window is present, the hovering is stopped
2386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2387 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2388 .build());
2389 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2390
2391 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002392 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002393
2394 // And a new hover gesture starts.
2395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2396 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2397 .build());
2398 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2399}
2400
2401/**
2402 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2403 * the obscuring window.
2404 */
2405TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2407 sp<FakeWindowHandle> window =
2408 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2409 window->setFrame(Rect(0, 0, 200, 200));
2410
2411 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002413
2414 // Start hovering in the window
2415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2416 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2417 .build());
2418 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2419
2420 // Now, an obscuring window appears!
2421 sp<FakeWindowHandle> obscuringWindow =
2422 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2423 ADISPLAY_ID_DEFAULT,
2424 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2425 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2426 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2427 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2428 obscuringWindow->setNoInputChannel(true);
2429 obscuringWindow->setFocusable(false);
2430 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002431 mDispatcher->onWindowInfosChanged(
2432 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002433
2434 // While this new obscuring window is present, the hovering continues. The event can't go to the
2435 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2437 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2438 .build());
2439 obscuringWindow->assertNoEvents();
2440 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2441
2442 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002443 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002444
2445 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2446 // so it should generate a HOVER_ENTER
2447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2448 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2449 .build());
2450 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2451
2452 // Now the MOVE should be getting dispatched normally
2453 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2454 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2455 .build());
2456 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2457}
2458
2459/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002460 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2461 * events are delivered to the window.
2462 */
2463TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2465 sp<FakeWindowHandle> window =
2466 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2467 window->setFrame(Rect(0, 0, 200, 200));
2468 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2469
2470 // Start hovering in the window
2471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2472 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2473 .build());
2474 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2475
2476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2477 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2478 .build());
2479 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2480
2481 // Scroll with the mouse
2482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2483 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2484 .build());
2485 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2486}
2487
2488using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2489
2490/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002491 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2492 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002493 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002494TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2496 sp<FakeWindowHandle> window =
2497 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2498 window->setFrame(Rect(0, 0, 200, 200));
2499
2500 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2501
2502 constexpr int32_t touchDeviceId = 4;
2503 constexpr int32_t stylusDeviceId = 2;
2504
2505 // Stylus down
2506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2507 .deviceId(stylusDeviceId)
2508 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2509 .build());
2510 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2511
2512 // Touch down
2513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2514 .deviceId(touchDeviceId)
2515 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2516 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002517
2518 // Touch move
2519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2520 .deviceId(touchDeviceId)
2521 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2522 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002523 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002524
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002525 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2527 .deviceId(stylusDeviceId)
2528 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2529 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002530 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2531 WithCoords(101, 111)));
2532
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002533 window->assertNoEvents();
2534}
2535
2536/**
2537 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002538 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002539 * Similar test as above, but with added SPY window.
2540 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002541TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2543 sp<FakeWindowHandle> window =
2544 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2545 sp<FakeWindowHandle> spyWindow =
2546 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2547 spyWindow->setFrame(Rect(0, 0, 200, 200));
2548 spyWindow->setTrustedOverlay(true);
2549 spyWindow->setSpy(true);
2550 window->setFrame(Rect(0, 0, 200, 200));
2551
2552 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2553
2554 constexpr int32_t touchDeviceId = 4;
2555 constexpr int32_t stylusDeviceId = 2;
2556
2557 // Stylus down
2558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2559 .deviceId(stylusDeviceId)
2560 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2561 .build());
2562 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2563 spyWindow->consumeMotionEvent(
2564 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2565
2566 // Touch down
2567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2568 .deviceId(touchDeviceId)
2569 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2570 .build());
2571
2572 // Touch move
2573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2574 .deviceId(touchDeviceId)
2575 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2576 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002577
2578 // Touch is ignored because stylus is already down
2579
2580 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2582 .deviceId(stylusDeviceId)
2583 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2584 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002585 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2586 WithCoords(101, 111)));
2587 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2588 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002589
2590 window->assertNoEvents();
2591 spyWindow->assertNoEvents();
2592}
2593
2594/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002595 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002596 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002597 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002598TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2600 sp<FakeWindowHandle> window =
2601 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2602 window->setFrame(Rect(0, 0, 200, 200));
2603
2604 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2605
2606 constexpr int32_t touchDeviceId = 4;
2607 constexpr int32_t stylusDeviceId = 2;
2608
2609 // Stylus down on the window
2610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2611 .deviceId(stylusDeviceId)
2612 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2613 .build());
2614 window->consumeMotionEvent(
2615 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2616
2617 // Touch down on window
2618 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2619 .deviceId(touchDeviceId)
2620 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2621 .build());
2622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2623 .deviceId(touchDeviceId)
2624 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2625 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002626
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002627 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002628
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002629 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2631 .deviceId(stylusDeviceId)
2632 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2633 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002634 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2635 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002637 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002638 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2639 .deviceId(touchDeviceId)
2640 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2641 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002642 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002643}
2644
2645/**
2646 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002647 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002648 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002649TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2651 sp<FakeWindowHandle> window =
2652 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2653 window->setFrame(Rect(0, 0, 200, 200));
2654
2655 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2656
2657 constexpr int32_t touchDeviceId = 4;
2658 constexpr int32_t stylusDeviceId = 2;
2659
2660 // Touch down on window
2661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2662 .deviceId(touchDeviceId)
2663 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2664 .build());
2665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2666 .deviceId(touchDeviceId)
2667 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2668 .build());
2669 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2670 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2671
2672 // Stylus hover on the window
2673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2674 .deviceId(stylusDeviceId)
2675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2676 .build());
2677 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2678 .deviceId(stylusDeviceId)
2679 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2680 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002681 // Stylus hover movement causes touch to be canceled
2682 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2683 WithCoords(141, 146)));
2684 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2685 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2686 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2687 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002688
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002689 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2691 .deviceId(touchDeviceId)
2692 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2693 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002694
2695 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002696}
2697
2698/**
2699 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2700 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2701 * become active.
2702 */
2703TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2705 sp<FakeWindowHandle> window =
2706 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2707 window->setFrame(Rect(0, 0, 200, 200));
2708
2709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2710
2711 constexpr int32_t stylusDeviceId1 = 3;
2712 constexpr int32_t stylusDeviceId2 = 5;
2713
2714 // Touch down on window
2715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2716 .deviceId(stylusDeviceId1)
2717 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2718 .build());
2719 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2720 .deviceId(stylusDeviceId1)
2721 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2722 .build());
2723 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2724 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2725
2726 // Second stylus down
2727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2728 .deviceId(stylusDeviceId2)
2729 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2730 .build());
2731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2732 .deviceId(stylusDeviceId2)
2733 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2734 .build());
2735
2736 // First stylus is canceled, second one takes over.
2737 window->consumeMotionEvent(
2738 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2739 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2740 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2741
2742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2743 .deviceId(stylusDeviceId1)
2744 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2745 .build());
2746 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002747 window->assertNoEvents();
2748}
2749
2750/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002751 * One window. Touch down on the window. Then, stylus down on the window from another device.
2752 * Ensure that is canceled, because stylus down should be preferred over touch.
2753 */
2754TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2756 sp<FakeWindowHandle> window =
2757 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2758 window->setFrame(Rect(0, 0, 200, 200));
2759
2760 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2761
2762 constexpr int32_t touchDeviceId = 4;
2763 constexpr int32_t stylusDeviceId = 2;
2764
2765 // Touch down on window
2766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2767 .deviceId(touchDeviceId)
2768 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2769 .build());
2770 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2771 .deviceId(touchDeviceId)
2772 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2773 .build());
2774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2775 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2776
2777 // Stylus down on the window
2778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2779 .deviceId(stylusDeviceId)
2780 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2781 .build());
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2783 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2784
2785 // Subsequent stylus movements are delivered correctly
2786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2787 .deviceId(stylusDeviceId)
2788 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2789 .build());
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2791 WithCoords(101, 111)));
2792}
2793
2794/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002795 * Two windows: a window on the left and a window on the right.
2796 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2797 * down. Then, on the left window, also place second touch pointer down.
2798 * This test tries to reproduce a crash.
2799 * In the buggy implementation, second pointer down on the left window would cause a crash.
2800 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002801TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002802 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2803 sp<FakeWindowHandle> leftWindow =
2804 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2805 leftWindow->setFrame(Rect(0, 0, 200, 200));
2806
2807 sp<FakeWindowHandle> rightWindow =
2808 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2809 rightWindow->setFrame(Rect(200, 0, 400, 200));
2810
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002811 mDispatcher->onWindowInfosChanged(
2812 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002813
2814 const int32_t touchDeviceId = 4;
2815 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002816
2817 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2819 .deviceId(mouseDeviceId)
2820 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2821 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002822 leftWindow->consumeMotionEvent(
2823 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2824
2825 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2827 .deviceId(mouseDeviceId)
2828 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2829 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2830 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002831
2832 leftWindow->consumeMotionEvent(
2833 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2834 leftWindow->consumeMotionEvent(
2835 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2836
Prabir Pradhan678438e2023-04-13 19:32:51 +00002837 mDispatcher->notifyMotion(
2838 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2839 .deviceId(mouseDeviceId)
2840 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2841 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2842 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2843 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002844 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2845
2846 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2848 .deviceId(touchDeviceId)
2849 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2850 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002851 leftWindow->assertNoEvents();
2852
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002853 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2854
2855 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002856 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2857 .deviceId(touchDeviceId)
2858 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2859 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2860 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002861 // Since this is now a new splittable pointer going down on the left window, and it's coming
2862 // from a different device, the current gesture in the left window (pointer down) should first
2863 // be canceled.
2864 leftWindow->consumeMotionEvent(
2865 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002866 leftWindow->consumeMotionEvent(
2867 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2868 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2869 // current implementation.
2870 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2871 rightWindow->consumeMotionEvent(
2872 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2873
2874 leftWindow->assertNoEvents();
2875 rightWindow->assertNoEvents();
2876}
2877
2878/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002879 * Two windows: a window on the left and a window on the right.
2880 * Mouse is hovered on the left window and stylus is hovered on the right window.
2881 */
2882TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2884 sp<FakeWindowHandle> leftWindow =
2885 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2886 leftWindow->setFrame(Rect(0, 0, 200, 200));
2887
2888 sp<FakeWindowHandle> rightWindow =
2889 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2890 rightWindow->setFrame(Rect(200, 0, 400, 200));
2891
2892 mDispatcher->onWindowInfosChanged(
2893 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2894
2895 const int32_t stylusDeviceId = 3;
2896 const int32_t mouseDeviceId = 6;
2897
2898 // Start hovering over the left window
2899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2900 .deviceId(mouseDeviceId)
2901 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2902 .build());
2903 leftWindow->consumeMotionEvent(
2904 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2905
2906 // Stylus hovered on right window
2907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2908 .deviceId(stylusDeviceId)
2909 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2910 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002911 rightWindow->consumeMotionEvent(
2912 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2913
2914 // Subsequent HOVER_MOVE events are dispatched correctly.
2915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2916 .deviceId(mouseDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2918 .build());
2919 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002920 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002921
2922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2923 .deviceId(stylusDeviceId)
2924 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2925 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002926 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002927 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002928
2929 leftWindow->assertNoEvents();
2930 rightWindow->assertNoEvents();
2931}
2932
2933/**
2934 * Three windows: a window on the left and a window on the right.
2935 * And a spy window that's positioned above all of them.
2936 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2937 * Check the stream that's received by the spy.
2938 */
2939TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2941
2942 sp<FakeWindowHandle> spyWindow =
2943 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2944 spyWindow->setFrame(Rect(0, 0, 400, 400));
2945 spyWindow->setTrustedOverlay(true);
2946 spyWindow->setSpy(true);
2947
2948 sp<FakeWindowHandle> leftWindow =
2949 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2950 leftWindow->setFrame(Rect(0, 0, 200, 200));
2951
2952 sp<FakeWindowHandle> rightWindow =
2953 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2954
2955 rightWindow->setFrame(Rect(200, 0, 400, 200));
2956
2957 mDispatcher->onWindowInfosChanged(
2958 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2959
2960 const int32_t stylusDeviceId = 1;
2961 const int32_t touchDeviceId = 2;
2962
2963 // Stylus down on the left window
2964 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2965 .deviceId(stylusDeviceId)
2966 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2967 .build());
2968 leftWindow->consumeMotionEvent(
2969 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2970 spyWindow->consumeMotionEvent(
2971 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2972
2973 // Touch down on the right window
2974 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2975 .deviceId(touchDeviceId)
2976 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2977 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002978 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002979 rightWindow->consumeMotionEvent(
2980 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002981
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002982 // Spy window does not receive touch events, because stylus events take precedence, and it
2983 // already has an active stylus gesture.
2984
2985 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2987 .deviceId(stylusDeviceId)
2988 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2989 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002990 leftWindow->consumeMotionEvent(
2991 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2992 spyWindow->consumeMotionEvent(
2993 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002994
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002995 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2997 .deviceId(touchDeviceId)
2998 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2999 .build());
3000 rightWindow->consumeMotionEvent(
3001 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003002
3003 spyWindow->assertNoEvents();
3004 leftWindow->assertNoEvents();
3005 rightWindow->assertNoEvents();
3006}
3007
3008/**
3009 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3010 * both.
3011 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003012 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003013 * At the same time, left and right should be getting independent streams of hovering and touch,
3014 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003015 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003016TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3018
3019 sp<FakeWindowHandle> spyWindow =
3020 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3021 spyWindow->setFrame(Rect(0, 0, 400, 400));
3022 spyWindow->setTrustedOverlay(true);
3023 spyWindow->setSpy(true);
3024
3025 sp<FakeWindowHandle> leftWindow =
3026 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3027 leftWindow->setFrame(Rect(0, 0, 200, 200));
3028
3029 sp<FakeWindowHandle> rightWindow =
3030 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3031 rightWindow->setFrame(Rect(200, 0, 400, 200));
3032
3033 mDispatcher->onWindowInfosChanged(
3034 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3035
3036 const int32_t stylusDeviceId = 1;
3037 const int32_t touchDeviceId = 2;
3038
3039 // Stylus hover on the left window
3040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3041 .deviceId(stylusDeviceId)
3042 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3043 .build());
3044 leftWindow->consumeMotionEvent(
3045 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3046 spyWindow->consumeMotionEvent(
3047 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3048
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003049 // Touch down on the right window. Spy doesn't receive this touch because it already has
3050 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3052 .deviceId(touchDeviceId)
3053 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3054 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003055 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003056 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003057 rightWindow->consumeMotionEvent(
3058 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3059
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003060 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3062 .deviceId(stylusDeviceId)
3063 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3064 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003065 leftWindow->consumeMotionEvent(
3066 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003067 spyWindow->consumeMotionEvent(
3068 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003069
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003070 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3072 .deviceId(touchDeviceId)
3073 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3074 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003075 rightWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3077
3078 spyWindow->assertNoEvents();
3079 leftWindow->assertNoEvents();
3080 rightWindow->assertNoEvents();
3081}
3082
3083/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003084 * On a single window, use two different devices: mouse and touch.
3085 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3086 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3087 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3088 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3089 * represent a new gesture.
3090 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003091TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3093 sp<FakeWindowHandle> window =
3094 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3095 window->setFrame(Rect(0, 0, 400, 400));
3096
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003097 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003098
3099 const int32_t touchDeviceId = 4;
3100 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003102 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3104 .deviceId(touchDeviceId)
3105 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3106 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003107 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003108 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3109 .deviceId(touchDeviceId)
3110 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3111 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3112 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003113 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003114 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3115 .deviceId(touchDeviceId)
3116 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3117 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3118 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003119 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3120 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3121 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3122
3123 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3125 .deviceId(mouseDeviceId)
3126 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3127 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3128 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003129
3130 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003131 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003132 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3133
Prabir Pradhan678438e2023-04-13 19:32:51 +00003134 mDispatcher->notifyMotion(
3135 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3136 .deviceId(mouseDeviceId)
3137 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3138 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3139 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3140 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003141 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3142
3143 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003144 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3145 .deviceId(touchDeviceId)
3146 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3147 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3148 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003149 // Since we already canceled this touch gesture, it will be ignored until a completely new
3150 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3151 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3152 // However, mouse movements should continue to work.
3153 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3154 .deviceId(mouseDeviceId)
3155 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3156 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3157 .build());
3158 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3159
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003160 window->assertNoEvents();
3161}
3162
3163/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003164 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3165 * the injected event.
3166 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003167TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3169 sp<FakeWindowHandle> window =
3170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3171 window->setFrame(Rect(0, 0, 400, 400));
3172
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003173 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003174
3175 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003176 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3177 // completion.
3178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003179 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003180 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3181 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003182 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003183 .build()));
3184 window->consumeMotionEvent(
3185 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3186
3187 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3188 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003193
3194 window->consumeMotionEvent(
3195 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3196 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3197}
3198
3199/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003200 * This test is similar to the test above, but the sequence of injected events is different.
3201 *
3202 * Two windows: a window on the left and a window on the right.
3203 * Mouse is hovered over the left window.
3204 * Next, we tap on the left window, where the cursor was last seen.
3205 *
3206 * After that, we inject one finger down onto the right window, and then a second finger down onto
3207 * the left window.
3208 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3209 * window (first), and then another on the left window (second).
3210 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3211 * In the buggy implementation, second finger down on the left window would cause a crash.
3212 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003213TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3215 sp<FakeWindowHandle> leftWindow =
3216 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3217 leftWindow->setFrame(Rect(0, 0, 200, 200));
3218
3219 sp<FakeWindowHandle> rightWindow =
3220 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3221 rightWindow->setFrame(Rect(200, 0, 400, 200));
3222
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003223 mDispatcher->onWindowInfosChanged(
3224 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003225
3226 const int32_t mouseDeviceId = 6;
3227 const int32_t touchDeviceId = 4;
3228 // Hover over the left window. Keep the cursor there.
3229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003230 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003231 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3232 AINPUT_SOURCE_MOUSE)
3233 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003234 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003235 .build()));
3236 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3237
3238 // Tap on left window
3239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003240 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003241 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3242 AINPUT_SOURCE_TOUCHSCREEN)
3243 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003244 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003245 .build()));
3246
3247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003248 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003249 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3250 AINPUT_SOURCE_TOUCHSCREEN)
3251 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003252 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003253 .build()));
3254 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3255 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3256 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3257
3258 // First finger down on right window
3259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003260 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003261 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3262 AINPUT_SOURCE_TOUCHSCREEN)
3263 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003264 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003265 .build()));
3266 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3267
3268 // Second finger down on the left window
3269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003271 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3272 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003273 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3274 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003275 .build()));
3276 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3277 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3278
3279 // No more events
3280 leftWindow->assertNoEvents();
3281 rightWindow->assertNoEvents();
3282}
3283
3284/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003285 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3286 * While the touch is down, new hover events from the stylus device should be ignored. After the
3287 * touch is gone, stylus hovering should start working again.
3288 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003289TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003290 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3291 sp<FakeWindowHandle> window =
3292 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3293 window->setFrame(Rect(0, 0, 200, 200));
3294
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003295 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003296
3297 const int32_t stylusDeviceId = 5;
3298 const int32_t touchDeviceId = 4;
3299 // Start hovering with stylus
3300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003301 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003302 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003303 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003304 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003305 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003306 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003307
3308 // Finger down on the window
3309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003310 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003311 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003313 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003314 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003315 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003316
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003317 // Continue hovering with stylus.
3318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003319 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003320 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3321 AINPUT_SOURCE_STYLUS)
3322 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003323 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003324 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003325 // Hovers continue to work
3326 window->consumeMotionEvent(
3327 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003328
3329 // Lift up the finger
3330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003331 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003332 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3333 AINPUT_SOURCE_TOUCHSCREEN)
3334 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003335 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003336 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3341 AINPUT_SOURCE_STYLUS)
3342 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003343 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003344 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003345 window->consumeMotionEvent(
3346 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003347 window->assertNoEvents();
3348}
3349
3350/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003351 * A spy window above a window with no input channel.
3352 * Start hovering with a stylus device, and then tap with it.
3353 * Ensure spy window receives the entire sequence.
3354 */
3355TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3357 sp<FakeWindowHandle> spyWindow =
3358 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3359 spyWindow->setFrame(Rect(0, 0, 200, 200));
3360 spyWindow->setTrustedOverlay(true);
3361 spyWindow->setSpy(true);
3362 sp<FakeWindowHandle> window =
3363 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3364 window->setNoInputChannel(true);
3365 window->setFrame(Rect(0, 0, 200, 200));
3366
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003367 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003368
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003369 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3371 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3372 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003373 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3374 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3376 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3377 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003378 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3379
3380 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3382 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3383 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003384 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3385
3386 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003387 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3388 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3389 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003390 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3391
3392 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3394 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3395 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003396 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3397 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003398 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3399 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3400 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003401 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3402
3403 // No more events
3404 spyWindow->assertNoEvents();
3405 window->assertNoEvents();
3406}
3407
3408/**
3409 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3410 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3411 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3412 * While the mouse is down, new move events from the touch device should be ignored.
3413 */
3414TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3416 sp<FakeWindowHandle> spyWindow =
3417 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3418 spyWindow->setFrame(Rect(0, 0, 200, 200));
3419 spyWindow->setTrustedOverlay(true);
3420 spyWindow->setSpy(true);
3421 sp<FakeWindowHandle> window =
3422 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3423 window->setFrame(Rect(0, 0, 200, 200));
3424
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003425 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003426
3427 const int32_t mouseDeviceId = 7;
3428 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003429
3430 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3432 .deviceId(mouseDeviceId)
3433 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3434 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003435 spyWindow->consumeMotionEvent(
3436 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3437 window->consumeMotionEvent(
3438 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3439
3440 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3442 .deviceId(touchDeviceId)
3443 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3444 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003445 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3446 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3447 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3448 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3449
Prabir Pradhan678438e2023-04-13 19:32:51 +00003450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3451 .deviceId(touchDeviceId)
3452 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3453 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003454 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3455 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3456
3457 // Pilfer the stream
3458 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3459 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3460
Prabir Pradhan678438e2023-04-13 19:32:51 +00003461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3462 .deviceId(touchDeviceId)
3463 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3464 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003465 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3466
3467 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3469 .deviceId(mouseDeviceId)
3470 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3472 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003473
3474 spyWindow->consumeMotionEvent(
3475 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3476 spyWindow->consumeMotionEvent(
3477 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3478 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3479
Prabir Pradhan678438e2023-04-13 19:32:51 +00003480 mDispatcher->notifyMotion(
3481 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3482 .deviceId(mouseDeviceId)
3483 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3484 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3485 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3486 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003487 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3488 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3489
3490 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3492 .deviceId(mouseDeviceId)
3493 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3494 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3495 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003496 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3497 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3498
3499 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003500 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3501 .deviceId(touchDeviceId)
3502 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3503 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003504
3505 // No more events
3506 spyWindow->assertNoEvents();
3507 window->assertNoEvents();
3508}
3509
3510/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003511 * On the display, have a single window, and also an area where there's no window.
3512 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3513 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3514 */
3515TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3517 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003518 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003519
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003520 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003521
3522 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003523 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003524
3525 mDispatcher->waitForIdle();
3526 window->assertNoEvents();
3527
3528 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003529 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003530 mDispatcher->waitForIdle();
3531 window->consumeMotionDown();
3532}
3533
3534/**
3535 * Same test as above, but instead of touching the empty space, the first touch goes to
3536 * non-touchable window.
3537 */
3538TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3540 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003541 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003542 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3543 window1->setTouchable(false);
3544 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003545 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003546 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3547
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003548 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003549
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003550 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003551 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003552
3553 mDispatcher->waitForIdle();
3554 window1->assertNoEvents();
3555 window2->assertNoEvents();
3556
3557 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003558 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003559 mDispatcher->waitForIdle();
3560 window2->consumeMotionDown();
3561}
3562
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003563/**
3564 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3565 * to the event time of the first ACTION_DOWN sent to the particular window.
3566 */
3567TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3568 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3569 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003570 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003571 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3572 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003573 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003574 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3575
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003576 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003577
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003578 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003579 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003580
3581 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003582
3583 MotionEvent* motionEvent1 = window1->consumeMotion();
3584 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003585 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003586 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3587 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003588
3589 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003590 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003591 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003592 MotionEvent* motionEvent2 = window2->consumeMotion();
3593 ASSERT_NE(motionEvent2, nullptr);
3594 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003595 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003596 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003597
3598 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003599 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003600 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003601 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003602
3603 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003604 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003605 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003606 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003607
3608 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3609 window1->consumeMotionMove();
3610 window1->assertNoEvents();
3611
3612 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003613 mDispatcher->notifyMotion(
3614 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003615 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003616 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003617
Prabir Pradhan678438e2023-04-13 19:32:51 +00003618 mDispatcher->notifyMotion(
3619 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003620 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003621 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003622}
3623
Garfield Tandf26e862020-07-01 20:18:19 -07003624TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003626 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003627 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003628 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003629 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003630 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003631 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003632
3633 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3634
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003635 mDispatcher->onWindowInfosChanged(
3636 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003637
3638 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003640 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003641 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3642 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003643 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003644 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003645 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003646
3647 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003649 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003650 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3651 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003652 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003653 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003654 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3655 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003656
3657 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003659 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003660 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3661 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003662 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003663 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003664 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3665 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003666
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003668 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003669 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3670 AINPUT_SOURCE_MOUSE)
3671 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3672 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003673 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003674 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003675 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003676
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003678 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003679 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3680 AINPUT_SOURCE_MOUSE)
3681 .buttonState(0)
3682 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003683 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003684 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003685 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003686
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003688 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003689 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3690 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003691 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003692 .build()));
3693 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3694
3695 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003697 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003698 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3699 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003700 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003701 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003702 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003703
3704 // No more events
3705 windowLeft->assertNoEvents();
3706 windowRight->assertNoEvents();
3707}
3708
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003709/**
3710 * Put two fingers down (and don't release them) and click the mouse button.
3711 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3712 * currently active gesture should be canceled, and the new one should proceed.
3713 */
3714TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3716 sp<FakeWindowHandle> window =
3717 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3718 window->setFrame(Rect(0, 0, 600, 800));
3719
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003720 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003721
3722 const int32_t touchDeviceId = 4;
3723 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003724
3725 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3727 .deviceId(touchDeviceId)
3728 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3729 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003730
Prabir Pradhan678438e2023-04-13 19:32:51 +00003731 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3732 .deviceId(touchDeviceId)
3733 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3734 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3735 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003736 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3737 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3738
3739 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003740 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3741 .deviceId(mouseDeviceId)
3742 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3743 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3744 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003745 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3746 WithPointerCount(2u)));
3747 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3748
Prabir Pradhan678438e2023-04-13 19:32:51 +00003749 mDispatcher->notifyMotion(
3750 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3751 .deviceId(mouseDeviceId)
3752 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3753 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3754 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3755 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003756 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3757
3758 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3759 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3761 .deviceId(touchDeviceId)
3762 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3763 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3764 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003765 window->assertNoEvents();
3766}
3767
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003768TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3770
3771 sp<FakeWindowHandle> spyWindow =
3772 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3773 spyWindow->setFrame(Rect(0, 0, 600, 800));
3774 spyWindow->setTrustedOverlay(true);
3775 spyWindow->setSpy(true);
3776 sp<FakeWindowHandle> window =
3777 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3778 window->setFrame(Rect(0, 0, 600, 800));
3779
3780 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003781 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003782
3783 // Send mouse cursor to the window
3784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003785 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003786 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3787 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003788 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003789 .build()));
3790
3791 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3792 WithSource(AINPUT_SOURCE_MOUSE)));
3793 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3794 WithSource(AINPUT_SOURCE_MOUSE)));
3795
3796 window->assertNoEvents();
3797 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003798}
3799
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003800TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3802
3803 sp<FakeWindowHandle> spyWindow =
3804 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3805 spyWindow->setFrame(Rect(0, 0, 600, 800));
3806 spyWindow->setTrustedOverlay(true);
3807 spyWindow->setSpy(true);
3808 sp<FakeWindowHandle> window =
3809 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3810 window->setFrame(Rect(0, 0, 600, 800));
3811
3812 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003813 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003814
3815 // Send mouse cursor to the window
3816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003817 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003818 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3819 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003820 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003821 .build()));
3822
3823 // Move mouse cursor
3824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003825 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003826 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3827 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003829 .build()));
3830
3831 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3832 WithSource(AINPUT_SOURCE_MOUSE)));
3833 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3834 WithSource(AINPUT_SOURCE_MOUSE)));
3835 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3836 WithSource(AINPUT_SOURCE_MOUSE)));
3837 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3838 WithSource(AINPUT_SOURCE_MOUSE)));
3839 // Touch down on the window
3840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003841 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003842 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3843 AINPUT_SOURCE_TOUCHSCREEN)
3844 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003845 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003846 .build()));
3847 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3848 WithSource(AINPUT_SOURCE_MOUSE)));
3849 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3850 WithSource(AINPUT_SOURCE_MOUSE)));
3851 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3852 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3853 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3854 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3855
3856 // pilfer the motion, retaining the gesture on the spy window.
3857 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3858 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3859 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3860
3861 // Touch UP on the window
3862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003863 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003864 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3865 AINPUT_SOURCE_TOUCHSCREEN)
3866 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003867 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003868 .build()));
3869 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3870 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3871
3872 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3873 // to send a new gesture. It should again go to both windows (spy and the window below), just
3874 // like the first gesture did, before pilfering. The window configuration has not changed.
3875
3876 // One more tap - DOWN
3877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003878 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003879 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3880 AINPUT_SOURCE_TOUCHSCREEN)
3881 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003882 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003883 .build()));
3884 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3885 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3886 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3887 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3888
3889 // Touch UP on the window
3890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003891 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003892 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3893 AINPUT_SOURCE_TOUCHSCREEN)
3894 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003895 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003896 .build()));
3897 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3898 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3899 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3900 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3901
3902 window->assertNoEvents();
3903 spyWindow->assertNoEvents();
3904}
3905
Garfield Tandf26e862020-07-01 20:18:19 -07003906// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3907// directly in this test.
3908TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003909 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003910 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003911 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003912 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003913
3914 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3915
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003916 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003917
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003919 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003920 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3921 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003923 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003924 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003925 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003927 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003928 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3929 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003930 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003931 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003932 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3933 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003934
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003936 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003937 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3938 AINPUT_SOURCE_MOUSE)
3939 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3940 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003941 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003942 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003943 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003944
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003946 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003947 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3948 AINPUT_SOURCE_MOUSE)
3949 .buttonState(0)
3950 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003951 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003952 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003953 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003954
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003956 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003957 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3958 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003959 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003960 .build()));
3961 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3962
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003963 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3964 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3965 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003966 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003967 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3968 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003969 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003970 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003971 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003972}
3973
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003974/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003975 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3976 * is generated.
3977 */
3978TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3979 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3980 sp<FakeWindowHandle> window =
3981 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3982 window->setFrame(Rect(0, 0, 1200, 800));
3983
3984 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3985
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003986 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003987
3988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003989 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003990 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3991 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003992 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003993 .build()));
3994 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3995
3996 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003997 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003998 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3999}
4000
4001/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004002 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4003 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004004TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4005 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4006 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4008 sp<FakeWindowHandle> window =
4009 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4010 window->setFrame(Rect(0, 0, 1200, 800));
4011
4012 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4013
4014 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4015
4016 MotionEventBuilder hoverEnterBuilder =
4017 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4018 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4019 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4021 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4023 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4024 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4025 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4026}
4027
4028/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004029 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4030 */
4031TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4033 sp<FakeWindowHandle> window =
4034 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4035 window->setFrame(Rect(0, 0, 100, 100));
4036
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004037 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004038
4039 const int32_t mouseDeviceId = 7;
4040 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004041
4042 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004043 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4044 .deviceId(mouseDeviceId)
4045 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4046 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004047 window->consumeMotionEvent(
4048 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4049
4050 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4052 .deviceId(touchDeviceId)
4053 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4054 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004055
4056 window->consumeMotionEvent(
4057 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4058 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4059}
4060
4061/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004062 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004063 * The tap causes a HOVER_EXIT event to be generated because the current event
4064 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004065 */
4066TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4067 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4068 sp<FakeWindowHandle> window =
4069 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4070 window->setFrame(Rect(0, 0, 100, 100));
4071
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004072 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004073 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4074 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4075 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004076 ASSERT_NO_FATAL_FAILURE(
4077 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4078 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004079
4080 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4082 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4083 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004084 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004085 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4086 WithSource(AINPUT_SOURCE_MOUSE))));
4087
4088 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004089 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4090 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4091
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004092 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4093 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4094 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004095 ASSERT_NO_FATAL_FAILURE(
4096 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4097 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4098}
4099
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004100TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4102 sp<FakeWindowHandle> windowDefaultDisplay =
4103 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4104 ADISPLAY_ID_DEFAULT);
4105 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4106 sp<FakeWindowHandle> windowSecondDisplay =
4107 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4108 SECOND_DISPLAY_ID);
4109 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4110
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004111 mDispatcher->onWindowInfosChanged(
4112 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004113
4114 // Set cursor position in window in default display and check that hover enter and move
4115 // events are generated.
4116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004117 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004118 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4119 AINPUT_SOURCE_MOUSE)
4120 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004121 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004122 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004123 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004124
4125 // Remove all windows in secondary display and check that no event happens on window in
4126 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004127 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4128
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004129 windowDefaultDisplay->assertNoEvents();
4130
4131 // Move cursor position in window in default display and check that only hover move
4132 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004133 mDispatcher->onWindowInfosChanged(
4134 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004136 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004137 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4138 AINPUT_SOURCE_MOUSE)
4139 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004140 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004141 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004142 windowDefaultDisplay->consumeMotionEvent(
4143 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4144 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004145 windowDefaultDisplay->assertNoEvents();
4146}
4147
Garfield Tan00f511d2019-06-12 16:55:40 -07004148TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004150
4151 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004152 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004153 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004154 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004155 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004156 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004157
4158 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4159
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004160 mDispatcher->onWindowInfosChanged(
4161 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004162
4163 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4164 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004166 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004167 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004168 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004169 windowRight->assertNoEvents();
4170}
4171
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004172TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004174 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4175 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004176 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004177
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004178 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004179 setFocusedWindow(window);
4180
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004181 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004182
Prabir Pradhan678438e2023-04-13 19:32:51 +00004183 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004184
4185 // Window should receive key down event.
4186 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4187
4188 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4189 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004190 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004191 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004192 AKEY_EVENT_FLAG_CANCELED);
4193}
4194
4195TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004197 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4198 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004199
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004201
Prabir Pradhan678438e2023-04-13 19:32:51 +00004202 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4203 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004204
4205 // Window should receive motion down event.
4206 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4207
4208 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4209 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004210 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004211 window->consumeMotionEvent(
4212 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004213}
4214
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004215TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4216 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4217 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4218 "Fake Window", ADISPLAY_ID_DEFAULT);
4219
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004220 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004221
4222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4224 .build());
4225
4226 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4227
4228 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4229 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4230 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4231
4232 // After the device has been reset, a new hovering stream can be sent to the window
4233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4234 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4235 .build());
4236 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4237}
4238
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004239TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4240 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004241 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4242 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004243 window->setFocusable(true);
4244
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004246 setFocusedWindow(window);
4247
4248 window->consumeFocusEvent(true);
4249
Prabir Pradhan678438e2023-04-13 19:32:51 +00004250 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004251 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4252 const nsecs_t injectTime = keyArgs.eventTime;
4253 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004254 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004255 // The dispatching time should be always greater than or equal to intercept key timeout.
4256 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4257 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4258 std::chrono::nanoseconds(interceptKeyTimeout).count());
4259}
4260
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004261/**
4262 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4263 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004264TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004266 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4267 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004268 window->setFocusable(true);
4269
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004270 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004271 setFocusedWindow(window);
4272
4273 window->consumeFocusEvent(true);
4274
Prabir Pradhan678438e2023-04-13 19:32:51 +00004275 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004276 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004277
4278 // Set a value that's significantly larger than the default consumption timeout. If the
4279 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4280 mFakePolicy->setInterceptKeyTimeout(600ms);
4281 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4282 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004283 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4284}
4285
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004286/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004287 * Two windows. First is a regular window. Second does not overlap with the first, and has
4288 * WATCH_OUTSIDE_TOUCH.
4289 * Both windows are owned by the same UID.
4290 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4291 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4292 */
4293TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004295 sp<FakeWindowHandle> window =
4296 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004297 window->setFrame(Rect{0, 0, 100, 100});
4298
4299 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004300 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004301 ADISPLAY_ID_DEFAULT);
4302 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4303 outsideWindow->setWatchOutsideTouch(true);
4304 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004305 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004306
4307 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004308 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4309 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4310 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004311 window->consumeMotionDown();
4312 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4313 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4314 outsideWindow->consumeMotionEvent(
4315 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4316}
4317
4318/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004319 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4320 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4321 * ACTION_OUTSIDE event is sent per gesture.
4322 */
4323TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4324 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004326 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4327 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004328 window->setWatchOutsideTouch(true);
4329 window->setFrame(Rect{0, 0, 100, 100});
4330 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4332 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004333 secondWindow->setFrame(Rect{100, 100, 200, 200});
4334 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004335 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4336 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004337 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004338 mDispatcher->onWindowInfosChanged(
4339 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004340
4341 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004342 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4343 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4344 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004345 window->assertNoEvents();
4346 secondWindow->assertNoEvents();
4347
4348 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4349 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004350 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4351 ADISPLAY_ID_DEFAULT,
4352 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004353 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4354 window->consumeMotionEvent(
4355 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004356 secondWindow->consumeMotionDown();
4357 thirdWindow->assertNoEvents();
4358
4359 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4360 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004361 mDispatcher->notifyMotion(
4362 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4363 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004364 window->assertNoEvents();
4365 secondWindow->consumeMotionMove();
4366 thirdWindow->consumeMotionDown();
4367}
4368
Prabir Pradhan814fe082022-07-22 20:22:18 +00004369TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004371 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4372 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004373 window->setFocusable(true);
4374
Patrick Williamsd828f302023-04-28 17:52:08 -05004375 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004376 setFocusedWindow(window);
4377
4378 window->consumeFocusEvent(true);
4379
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4381 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4382 mDispatcher->notifyKey(keyDown);
4383 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004384
4385 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4386 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4387
4388 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004389 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004390
4391 window->consumeFocusEvent(false);
4392
Prabir Pradhan678438e2023-04-13 19:32:51 +00004393 mDispatcher->notifyKey(keyDown);
4394 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004395 window->assertNoEvents();
4396}
4397
Arthur Hung96483742022-11-15 03:30:48 +00004398TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4399 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4400 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4401 "Fake Window", ADISPLAY_ID_DEFAULT);
4402 // Ensure window is non-split and have some transform.
4403 window->setPreventSplitting(true);
4404 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004405 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004406
4407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004408 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004409 {50, 50}))
4410 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4411 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4412
4413 const MotionEvent secondFingerDownEvent =
4414 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4415 .displayId(ADISPLAY_ID_DEFAULT)
4416 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004417 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4418 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004419 .build();
4420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004421 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004422 InputEventInjectionSync::WAIT_FOR_RESULT))
4423 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4424
4425 const MotionEvent* event = window->consumeMotion();
4426 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4427 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4428 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4429 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4430 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4431}
4432
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004433/**
4434 * Two windows: a splittable and a non-splittable.
4435 * The non-splittable window shouldn't receive any "incomplete" gestures.
4436 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4437 * The second pointer should be dropped because the initial window is splittable, so it won't get
4438 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4439 * "incomplete" gestures.
4440 */
4441TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4442 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4443 sp<FakeWindowHandle> leftWindow =
4444 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4445 ADISPLAY_ID_DEFAULT);
4446 leftWindow->setPreventSplitting(false);
4447 leftWindow->setFrame(Rect(0, 0, 100, 100));
4448 sp<FakeWindowHandle> rightWindow =
4449 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4450 ADISPLAY_ID_DEFAULT);
4451 rightWindow->setPreventSplitting(true);
4452 rightWindow->setFrame(Rect(100, 100, 200, 200));
4453 mDispatcher->onWindowInfosChanged(
4454 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4455
4456 // Touch down on left, splittable window
4457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4458 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4459 .build());
4460 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4461
4462 mDispatcher->notifyMotion(
4463 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4464 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4465 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4466 .build());
4467 leftWindow->assertNoEvents();
4468 rightWindow->assertNoEvents();
4469}
4470
Harry Cuttsb166c002023-05-09 13:06:05 +00004471TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
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));
4476 sp<FakeWindowHandle> trustedOverlay =
4477 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4478 ADISPLAY_ID_DEFAULT);
4479 trustedOverlay->setSpy(true);
4480 trustedOverlay->setTrustedOverlay(true);
4481
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004482 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004483
4484 // Start a three-finger touchpad swipe
4485 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4486 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4487 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4488 .build());
4489 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4490 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4491 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4492 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4493 .build());
4494 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4495 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4496 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4497 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4498 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4499 .build());
4500
4501 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4502 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4503 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4504
4505 // Move the swipe a bit
4506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4507 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4508 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4509 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4510 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4511 .build());
4512
4513 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4514
4515 // End the swipe
4516 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4517 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4518 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4519 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4520 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4521 .build());
4522 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4523 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4524 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4525 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4526 .build());
4527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4528 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4529 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4530 .build());
4531
4532 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4533 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4534 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4535
4536 window->assertNoEvents();
4537}
4538
4539TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4541 sp<FakeWindowHandle> window =
4542 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4543 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004544 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004545
4546 // Start a three-finger touchpad swipe
4547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4548 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4549 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4550 .build());
4551 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4552 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4553 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4554 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4555 .build());
4556 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4557 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4558 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4559 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4560 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4561 .build());
4562
4563 // Move the swipe a bit
4564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4565 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4566 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4567 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4568 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4569 .build());
4570
4571 // End the swipe
4572 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4573 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4574 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4575 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4576 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4577 .build());
4578 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4579 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4580 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4581 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4582 .build());
4583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4584 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4585 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4586 .build());
4587
4588 window->assertNoEvents();
4589}
4590
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004591/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004592 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4593 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004594 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004595 */
4596TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4598 sp<FakeWindowHandle> window =
4599 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4600 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004601 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004602
4603 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4604 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4605 .downTime(baseTime + 10)
4606 .eventTime(baseTime + 10)
4607 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4608 .build());
4609
4610 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4611
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004612 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004613 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004614
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004615 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004616
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004617 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4618 .downTime(baseTime + 10)
4619 .eventTime(baseTime + 30)
4620 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4621 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4622 .build());
4623
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004624 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4625
4626 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004627 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4628 .downTime(baseTime + 10)
4629 .eventTime(baseTime + 40)
4630 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4631 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4632 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004633
4634 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4635
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004636 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4637 .downTime(baseTime + 10)
4638 .eventTime(baseTime + 50)
4639 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4640 .build());
4641
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004642 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4643
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4645 .downTime(baseTime + 60)
4646 .eventTime(baseTime + 60)
4647 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4648 .build());
4649
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004650 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004651}
4652
4653/**
Hu Guo771a7692023-09-17 20:51:08 +08004654 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4655 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4656 * its coordinates should be converted by the transform of the windows of target screen.
4657 */
4658TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4659 // This case will create a window and a spy window on the default display and mirror
4660 // window on the second display. cancel event is sent through spy window pilferPointers
4661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4662
4663 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4664 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4665 spyWindowDefaultDisplay->setTrustedOverlay(true);
4666 spyWindowDefaultDisplay->setSpy(true);
4667
4668 sp<FakeWindowHandle> windowDefaultDisplay =
4669 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4670 ADISPLAY_ID_DEFAULT);
4671 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4672
4673 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4674 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4675
4676 // Add the windows to the dispatcher
4677 mDispatcher->onWindowInfosChanged(
4678 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4679 *windowSecondDisplay->getInfo()},
4680 {},
4681 0,
4682 0});
4683
4684 // Send down to ADISPLAY_ID_DEFAULT
4685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4687 {100, 100}))
4688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4689
4690 spyWindowDefaultDisplay->consumeMotionDown();
4691 windowDefaultDisplay->consumeMotionDown();
4692
4693 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4694
4695 // windowDefaultDisplay gets cancel
4696 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4697 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4698
4699 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4700 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4701 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4702 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4703 EXPECT_EQ(100, event->getX(0));
4704 EXPECT_EQ(100, event->getY(0));
4705}
4706
4707/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004708 * Ensure the correct coordinate spaces are used by InputDispatcher.
4709 *
4710 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4711 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4712 * space.
4713 */
4714class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4715public:
4716 void SetUp() override {
4717 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004718 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004719 }
4720
4721 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4722 gui::DisplayInfo info;
4723 info.displayId = displayId;
4724 info.transform = transform;
4725 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004726 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004727 }
4728
4729 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4730 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004731 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004732 }
4733
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004734 void removeAllWindowsAndDisplays() {
4735 mDisplayInfos.clear();
4736 mWindowInfos.clear();
4737 }
4738
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004739 // Set up a test scenario where the display has a scaled projection and there are two windows
4740 // on the display.
4741 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4742 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4743 // respectively.
4744 ui::Transform displayTransform;
4745 displayTransform.set(2, 0, 0, 4);
4746 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4747
4748 std::shared_ptr<FakeApplicationHandle> application =
4749 std::make_shared<FakeApplicationHandle>();
4750
4751 // Add two windows to the display. Their frames are represented in the display space.
4752 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004753 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4754 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004755 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4756 addWindow(firstWindow);
4757
4758 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004759 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4760 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004761 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4762 addWindow(secondWindow);
4763 return {std::move(firstWindow), std::move(secondWindow)};
4764 }
4765
4766private:
4767 std::vector<gui::DisplayInfo> mDisplayInfos;
4768 std::vector<gui::WindowInfo> mWindowInfos;
4769};
4770
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004771TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004772 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4773 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004774 // selected so that if the hit test was performed with the point and the bounds being in
4775 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004776 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4777 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4778 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004779
4780 firstWindow->consumeMotionDown();
4781 secondWindow->assertNoEvents();
4782}
4783
4784// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4785// the event should be treated as being in the logical display space.
4786TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4787 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4788 // Send down to the first window. The point is represented in the logical display space. The
4789 // point is selected so that if the hit test was done in logical display space, then it would
4790 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004791 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004792 PointF{75 * 2, 55 * 4});
4793
4794 firstWindow->consumeMotionDown();
4795 secondWindow->assertNoEvents();
4796}
4797
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004798// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4799// event should be treated as being in the logical display space.
4800TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4801 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4802
4803 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4804 ui::Transform injectedEventTransform;
4805 injectedEventTransform.set(matrix);
4806 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4807 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4808
4809 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4810 .displayId(ADISPLAY_ID_DEFAULT)
4811 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004812 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004813 .x(untransformedPoint.x)
4814 .y(untransformedPoint.y))
4815 .build();
4816 event.transform(matrix);
4817
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004818 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004819 InputEventInjectionSync::WAIT_FOR_RESULT);
4820
4821 firstWindow->consumeMotionDown();
4822 secondWindow->assertNoEvents();
4823}
4824
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004825TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4826 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4827
4828 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004829 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4830 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4831 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004832
4833 firstWindow->assertNoEvents();
4834 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004835 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004836 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4837
4838 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4839 EXPECT_EQ(300, event->getRawX(0));
4840 EXPECT_EQ(880, event->getRawY(0));
4841
4842 // Ensure that the x and y values are in the window's coordinate space.
4843 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4844 // the logical display space. This will be the origin of the window space.
4845 EXPECT_EQ(100, event->getX(0));
4846 EXPECT_EQ(80, event->getY(0));
4847}
4848
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004849TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4850 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4851 // The monitor will always receive events in the logical display's coordinate space, because
4852 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004853 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004854
4855 // Send down to the first window.
4856 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4857 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4858 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4859 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4860
4861 // Second pointer goes down on second window.
4862 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4863 ADISPLAY_ID_DEFAULT,
4864 {PointF{50, 100}, PointF{150, 220}}));
4865 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4866 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4867 {1, PointF{300, 880}}};
4868 monitor.consumeMotionEvent(
4869 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4870
4871 mDispatcher->cancelCurrentTouch();
4872
4873 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4874 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4875 monitor.consumeMotionEvent(
4876 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4877}
4878
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004879TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4880 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4881
4882 // Send down to the first window.
4883 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4884 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4885 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4886
4887 // The pointer is transferred to the second window, and the second window receives it in the
4888 // correct coordinate space.
4889 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4890 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4891 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4892}
4893
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004894TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4895 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4896
4897 // Send hover move to the second window, and ensure it shows up as hover enter.
4898 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4899 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4900 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4901 WithCoords(100, 80), WithRawCoords(300, 880)));
4902
4903 // Touch down at the same location and ensure a hover exit is synthesized.
4904 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4905 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4906 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4907 WithRawCoords(300, 880)));
4908 secondWindow->consumeMotionEvent(
4909 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4910 secondWindow->assertNoEvents();
4911 firstWindow->assertNoEvents();
4912}
4913
Prabir Pradhan453ae732023-10-13 14:30:14 +00004914// Same as above, but while the window is being mirrored.
4915TEST_F(InputDispatcherDisplayProjectionTest,
4916 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4917 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4918
4919 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4920 ui::Transform secondDisplayTransform;
4921 secondDisplayTransform.set(matrix);
4922 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4923
4924 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4925 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4926 addWindow(secondWindowClone);
4927
4928 // Send hover move to the second window, and ensure it shows up as hover enter.
4929 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4930 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4931 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4932 WithCoords(100, 80), WithRawCoords(300, 880)));
4933
4934 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4935 // display.
4936 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4937 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4938 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4939 WithRawCoords(300, 880)));
4940 secondWindow->consumeMotionEvent(
4941 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4942 secondWindow->assertNoEvents();
4943 firstWindow->assertNoEvents();
4944}
4945
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004946TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4947 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4948
4949 // Send hover enter to second window
4950 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4951 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4952 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4953 WithCoords(100, 80), WithRawCoords(300, 880)));
4954
4955 mDispatcher->cancelCurrentTouch();
4956
4957 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4958 WithRawCoords(300, 880)));
4959 secondWindow->assertNoEvents();
4960 firstWindow->assertNoEvents();
4961}
4962
Prabir Pradhan453ae732023-10-13 14:30:14 +00004963// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004964TEST_F(InputDispatcherDisplayProjectionTest,
4965 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4966 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4967
4968 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4969 ui::Transform secondDisplayTransform;
4970 secondDisplayTransform.set(matrix);
4971 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4972
4973 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4974 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4975 addWindow(secondWindowClone);
4976
4977 // Send hover enter to second window
4978 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4979 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4980 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4981 WithCoords(100, 80), WithRawCoords(300, 880),
4982 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4983
4984 mDispatcher->cancelCurrentTouch();
4985
4986 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4987 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4988 WithRawCoords(300, 880),
4989 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4990 secondWindow->assertNoEvents();
4991 firstWindow->assertNoEvents();
4992}
4993
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004994/** Ensure consistent behavior of InputDispatcher in all orientations. */
4995class InputDispatcherDisplayOrientationFixture
4996 : public InputDispatcherDisplayProjectionTest,
4997 public ::testing::WithParamInterface<ui::Rotation> {};
4998
4999// This test verifies the touchable region of a window for all rotations of the display by tapping
5000// in different locations on the display, specifically points close to the four corners of a
5001// window.
5002TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5003 constexpr static int32_t displayWidth = 400;
5004 constexpr static int32_t displayHeight = 800;
5005
5006 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5007
5008 const auto rotation = GetParam();
5009
5010 // Set up the display with the specified rotation.
5011 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5012 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5013 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5014 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5015 logicalDisplayWidth, logicalDisplayHeight);
5016 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5017
5018 // Create a window with its bounds determined in the logical display.
5019 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5020 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5021 sp<FakeWindowHandle> window =
5022 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5023 window->setFrame(frameInDisplay, displayTransform);
5024 addWindow(window);
5025
5026 // The following points in logical display space should be inside the window.
5027 static const std::array<vec2, 4> insidePoints{
5028 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5029 for (const auto pointInsideWindow : insidePoints) {
5030 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5031 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005032 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5033 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5034 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005035 window->consumeMotionDown();
5036
Prabir Pradhan678438e2023-04-13 19:32:51 +00005037 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5038 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5039 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005040 window->consumeMotionUp();
5041 }
5042
5043 // The following points in logical display space should be outside the window.
5044 static const std::array<vec2, 5> outsidePoints{
5045 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5046 for (const auto pointOutsideWindow : outsidePoints) {
5047 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5048 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005049 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5050 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5051 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005052
Prabir Pradhan678438e2023-04-13 19:32:51 +00005053 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5054 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5055 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005056 }
5057 window->assertNoEvents();
5058}
5059
5060// Run the precision tests for all rotations.
5061INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5062 InputDispatcherDisplayOrientationFixture,
5063 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5064 ui::ROTATION_270),
5065 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5066 return ftl::enum_string(testParamInfo.param);
5067 });
5068
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005069using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5070 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005071
5072class TransferTouchFixture : public InputDispatcherTest,
5073 public ::testing::WithParamInterface<TransferFunction> {};
5074
5075TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005077
5078 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005079 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005080 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5081 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005082 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005083 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005084 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5085 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005086 sp<FakeWindowHandle> wallpaper =
5087 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5088 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005089 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005090 mDispatcher->onWindowInfosChanged(
5091 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005092
5093 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005094 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5095 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005096
Svet Ganov5d3bc372020-01-26 23:11:07 -08005097 // Only the first window should get the down event
5098 firstWindow->consumeMotionDown();
5099 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005100 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005101
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005102 // Transfer touch to the second window
5103 TransferFunction f = GetParam();
5104 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5105 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005106 // The first window gets cancel and the second gets down
5107 firstWindow->consumeMotionCancel();
5108 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005109 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005110
5111 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005112 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5113 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005114 // The first window gets no events and the second gets up
5115 firstWindow->assertNoEvents();
5116 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005117 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005118}
5119
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005120/**
5121 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5122 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5123 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5124 * natural to the user.
5125 * In this test, we are sending a pointer to both spy window and first window. We then try to
5126 * transfer touch to the second window. The dispatcher should identify the first window as the
5127 * one that should lose the gesture, and therefore the action should be to move the gesture from
5128 * the first window to the second.
5129 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5130 * the other API, as well.
5131 */
5132TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5133 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5134
5135 // Create a couple of windows + a spy window
5136 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005137 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005138 spyWindow->setTrustedOverlay(true);
5139 spyWindow->setSpy(true);
5140 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005141 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005142 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005143 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005144
5145 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005146 mDispatcher->onWindowInfosChanged(
5147 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005148
5149 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005150 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5151 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005152 // Only the first window and spy should get the down event
5153 spyWindow->consumeMotionDown();
5154 firstWindow->consumeMotionDown();
5155
5156 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5157 // if f === 'transferTouch'.
5158 TransferFunction f = GetParam();
5159 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5160 ASSERT_TRUE(success);
5161 // The first window gets cancel and the second gets down
5162 firstWindow->consumeMotionCancel();
5163 secondWindow->consumeMotionDown();
5164
5165 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5167 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005168 // The first window gets no events and the second+spy get up
5169 firstWindow->assertNoEvents();
5170 spyWindow->consumeMotionUp();
5171 secondWindow->consumeMotionUp();
5172}
5173
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005174TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005176
5177 PointF touchPoint = {10, 10};
5178
5179 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005180 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005181 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5182 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005183 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005184 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005185 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5186 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005187 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005188
5189 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005190 mDispatcher->onWindowInfosChanged(
5191 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005192
5193 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005194 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5195 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5196 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005197 // Only the first window should get the down event
5198 firstWindow->consumeMotionDown();
5199 secondWindow->assertNoEvents();
5200
5201 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005202 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5203 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005204 // Only the first window should get the pointer down event
5205 firstWindow->consumeMotionPointerDown(1);
5206 secondWindow->assertNoEvents();
5207
5208 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005209 TransferFunction f = GetParam();
5210 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5211 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005212 // The first window gets cancel and the second gets down and pointer down
5213 firstWindow->consumeMotionCancel();
5214 secondWindow->consumeMotionDown();
5215 secondWindow->consumeMotionPointerDown(1);
5216
5217 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005218 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5219 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005220 // The first window gets nothing and the second gets pointer up
5221 firstWindow->assertNoEvents();
5222 secondWindow->consumeMotionPointerUp(1);
5223
5224 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005225 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5226 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005227 // The first window gets nothing and the second gets up
5228 firstWindow->assertNoEvents();
5229 secondWindow->consumeMotionUp();
5230}
5231
Arthur Hungc539dbb2022-12-08 07:45:36 +00005232TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5234
5235 // Create a couple of windows
5236 sp<FakeWindowHandle> firstWindow =
5237 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5238 ADISPLAY_ID_DEFAULT);
5239 firstWindow->setDupTouchToWallpaper(true);
5240 sp<FakeWindowHandle> secondWindow =
5241 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5242 ADISPLAY_ID_DEFAULT);
5243 secondWindow->setDupTouchToWallpaper(true);
5244
5245 sp<FakeWindowHandle> wallpaper1 =
5246 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5247 wallpaper1->setIsWallpaper(true);
5248
5249 sp<FakeWindowHandle> wallpaper2 =
5250 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5251 wallpaper2->setIsWallpaper(true);
5252 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005253 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5254 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5255 {},
5256 0,
5257 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005258
5259 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005260 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5261 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005262
5263 // Only the first window should get the down event
5264 firstWindow->consumeMotionDown();
5265 secondWindow->assertNoEvents();
5266 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5267 wallpaper2->assertNoEvents();
5268
5269 // Transfer touch focus to the second window
5270 TransferFunction f = GetParam();
5271 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5272 ASSERT_TRUE(success);
5273
5274 // The first window gets cancel and the second gets down
5275 firstWindow->consumeMotionCancel();
5276 secondWindow->consumeMotionDown();
5277 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5278 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5279
5280 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005281 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5282 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283 // The first window gets no events and the second gets up
5284 firstWindow->assertNoEvents();
5285 secondWindow->consumeMotionUp();
5286 wallpaper1->assertNoEvents();
5287 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5288}
5289
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005290// For the cases of single pointer touch and two pointers non-split touch, the api's
5291// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5292// for the case where there are multiple pointers split across several windows.
5293INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5294 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005295 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5296 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005297 return dispatcher->transferTouch(destChannelToken,
5298 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005299 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005300 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5301 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005302 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005303 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005304 }));
5305
Svet Ganov5d3bc372020-01-26 23:11:07 -08005306TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005308
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005309 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005310 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5311 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005312 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005313
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005314 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005315 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5316 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005317 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005318
5319 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005320 mDispatcher->onWindowInfosChanged(
5321 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005322
5323 PointF pointInFirst = {300, 200};
5324 PointF pointInSecond = {300, 600};
5325
5326 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005327 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5328 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5329 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005330 // Only the first window should get the down event
5331 firstWindow->consumeMotionDown();
5332 secondWindow->assertNoEvents();
5333
5334 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005335 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5336 ADISPLAY_ID_DEFAULT,
5337 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005338 // The first window gets a move and the second a down
5339 firstWindow->consumeMotionMove();
5340 secondWindow->consumeMotionDown();
5341
5342 // Transfer touch focus to the second window
5343 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5344 // The first window gets cancel and the new gets pointer down (it already saw down)
5345 firstWindow->consumeMotionCancel();
5346 secondWindow->consumeMotionPointerDown(1);
5347
5348 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5350 ADISPLAY_ID_DEFAULT,
5351 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005352 // The first window gets nothing and the second gets pointer up
5353 firstWindow->assertNoEvents();
5354 secondWindow->consumeMotionPointerUp(1);
5355
5356 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5358 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005359 // The first window gets nothing and the second gets up
5360 firstWindow->assertNoEvents();
5361 secondWindow->consumeMotionUp();
5362}
5363
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005364// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5365// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5366// touch is not supported, so the touch should continue on those windows and the transferred-to
5367// window should get nothing.
5368TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5369 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5370
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005371 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005372 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5373 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005374 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005375
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005376 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005377 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5378 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005379 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005380
5381 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005382 mDispatcher->onWindowInfosChanged(
5383 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005384
5385 PointF pointInFirst = {300, 200};
5386 PointF pointInSecond = {300, 600};
5387
5388 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005389 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5390 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5391 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005392 // Only the first window should get the down event
5393 firstWindow->consumeMotionDown();
5394 secondWindow->assertNoEvents();
5395
5396 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005397 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5398 ADISPLAY_ID_DEFAULT,
5399 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005400 // The first window gets a move and the second a down
5401 firstWindow->consumeMotionMove();
5402 secondWindow->consumeMotionDown();
5403
5404 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005405 const bool transferred =
5406 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005407 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5408 ASSERT_FALSE(transferred);
5409 firstWindow->assertNoEvents();
5410 secondWindow->assertNoEvents();
5411
5412 // The rest of the dispatch should proceed as normal
5413 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005414 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5415 ADISPLAY_ID_DEFAULT,
5416 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005417 // The first window gets MOVE and the second gets pointer up
5418 firstWindow->consumeMotionMove();
5419 secondWindow->consumeMotionUp();
5420
5421 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5423 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005424 // The first window gets nothing and the second gets up
5425 firstWindow->consumeMotionUp();
5426 secondWindow->assertNoEvents();
5427}
5428
Arthur Hungabbb9d82021-09-01 14:52:30 +00005429// This case will create two windows and one mirrored window on the default display and mirror
5430// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5431// the windows info of second display before default display.
5432TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5434 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005435 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005436 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005437 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005438 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005439 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005440
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005441 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005442 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005443
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005444 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005445 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005446
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005447 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005448 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005449
5450 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005451 mDispatcher->onWindowInfosChanged(
5452 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5453 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5454 *secondWindowInPrimary->getInfo()},
5455 {},
5456 0,
5457 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005458
5459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005460 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005461 {50, 50}))
5462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5463
5464 // Window should receive motion event.
5465 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5466
5467 // Transfer touch focus
5468 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5469 secondWindowInPrimary->getToken()));
5470 // The first window gets cancel.
5471 firstWindowInPrimary->consumeMotionCancel();
5472 secondWindowInPrimary->consumeMotionDown();
5473
5474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005475 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005476 ADISPLAY_ID_DEFAULT, {150, 50}))
5477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5478 firstWindowInPrimary->assertNoEvents();
5479 secondWindowInPrimary->consumeMotionMove();
5480
5481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005482 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005483 {150, 50}))
5484 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5485 firstWindowInPrimary->assertNoEvents();
5486 secondWindowInPrimary->consumeMotionUp();
5487}
5488
5489// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5490// 'transferTouch' api.
5491TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5492 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5493 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005494 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005495 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005496 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005497 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005498 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005499
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005500 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005501 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005502
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005503 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005504 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005505
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005506 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005507 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005508
5509 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005510 mDispatcher->onWindowInfosChanged(
5511 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5512 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5513 *secondWindowInPrimary->getInfo()},
5514 {},
5515 0,
5516 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005517
5518 // Touch on second display.
5519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005520 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5521 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5523
5524 // Window should receive motion event.
5525 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5526
5527 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005528 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005529
5530 // The first window gets cancel.
5531 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5532 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5533
5534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005535 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005536 SECOND_DISPLAY_ID, {150, 50}))
5537 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5538 firstWindowInPrimary->assertNoEvents();
5539 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5540
5541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005542 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5544 firstWindowInPrimary->assertNoEvents();
5545 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5546}
5547
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005548TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5551 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005552
Vishnu Nair47074b82020-08-14 11:54:47 -07005553 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005555 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005556
5557 window->consumeFocusEvent(true);
5558
Prabir Pradhan678438e2023-04-13 19:32:51 +00005559 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005560
5561 // Window should receive key down event.
5562 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005563
5564 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005565 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005566 mFakePolicy->assertUserActivityPoked();
5567}
5568
5569TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5571 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5572 "Fake Window", ADISPLAY_ID_DEFAULT);
5573
5574 window->setDisableUserActivity(true);
5575 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005576 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005577 setFocusedWindow(window);
5578
5579 window->consumeFocusEvent(true);
5580
5581 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5582
5583 // Window should receive key down event.
5584 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5585
5586 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005587 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005588 mFakePolicy->assertUserActivityNotPoked();
5589}
5590
5591TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5592 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5593 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5594 "Fake Window", ADISPLAY_ID_DEFAULT);
5595
5596 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005597 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005598 setFocusedWindow(window);
5599
5600 window->consumeFocusEvent(true);
5601
5602 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5603 mDispatcher->waitForIdle();
5604
5605 // System key is not passed down
5606 window->assertNoEvents();
5607
5608 // Should have poked user activity
5609 mFakePolicy->assertUserActivityPoked();
5610}
5611
5612TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5613 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5614 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5615 "Fake Window", ADISPLAY_ID_DEFAULT);
5616
5617 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005618 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005619 setFocusedWindow(window);
5620
5621 window->consumeFocusEvent(true);
5622
5623 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5624 mDispatcher->waitForIdle();
5625
5626 // System key is not passed down
5627 window->assertNoEvents();
5628
5629 // Should have poked user activity
5630 mFakePolicy->assertUserActivityPoked();
5631}
5632
5633TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5635 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5636 "Fake Window", ADISPLAY_ID_DEFAULT);
5637
5638 window->setDisableUserActivity(true);
5639 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005640 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005641 setFocusedWindow(window);
5642
5643 window->consumeFocusEvent(true);
5644
5645 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5646 mDispatcher->waitForIdle();
5647
5648 // System key is not passed down
5649 window->assertNoEvents();
5650
5651 // Should have poked user activity
5652 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005653}
5654
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005655TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5657 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5658 "Fake Window", ADISPLAY_ID_DEFAULT);
5659
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005660 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005661
5662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005663 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005664 ADISPLAY_ID_DEFAULT, {100, 100}))
5665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5666
5667 window->consumeMotionEvent(
5668 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5669
5670 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005671 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005672 mFakePolicy->assertUserActivityPoked();
5673}
5674
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005675TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005676 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005677 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5678 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005679
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005680 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005681
Prabir Pradhan678438e2023-04-13 19:32:51 +00005682 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005683 mDispatcher->waitForIdle();
5684
5685 window->assertNoEvents();
5686}
5687
5688// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5689TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005690 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005691 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5692 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005693
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005694 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005695
5696 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005697 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005698 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005699 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5700 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005701
5702 // Window should receive only the motion event
5703 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5704 window->assertNoEvents(); // Key event or focus event will not be received
5705}
5706
arthurhungea3f4fc2020-12-21 23:18:53 +08005707TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5709
arthurhungea3f4fc2020-12-21 23:18:53 +08005710 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005711 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5712 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005713 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005714
arthurhungea3f4fc2020-12-21 23:18:53 +08005715 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005716 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5717 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005718 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005719
5720 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005721 mDispatcher->onWindowInfosChanged(
5722 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005723
5724 PointF pointInFirst = {300, 200};
5725 PointF pointInSecond = {300, 600};
5726
5727 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005728 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5729 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5730 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005731 // Only the first window should get the down event
5732 firstWindow->consumeMotionDown();
5733 secondWindow->assertNoEvents();
5734
5735 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005736 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5737 ADISPLAY_ID_DEFAULT,
5738 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005739 // The first window gets a move and the second a down
5740 firstWindow->consumeMotionMove();
5741 secondWindow->consumeMotionDown();
5742
5743 // Send pointer cancel to the second window
5744 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005745 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005746 {pointInFirst, pointInSecond});
5747 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005748 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005749 // The first window gets move and the second gets cancel.
5750 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5751 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5752
5753 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005754 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5755 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005756 // The first window gets up and the second gets nothing.
5757 firstWindow->consumeMotionUp();
5758 secondWindow->assertNoEvents();
5759}
5760
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005761TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5763
5764 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005765 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005767 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5768 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5769 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5770
Harry Cutts33476232023-01-30 19:57:29 +00005771 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005772 window->assertNoEvents();
5773 mDispatcher->waitForIdle();
5774}
5775
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005776using InputDispatcherMonitorTest = InputDispatcherTest;
5777
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005778/**
5779 * Two entities that receive touch: A window, and a global monitor.
5780 * The touch goes to the window, and then the window disappears.
5781 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5782 * for the monitor, as well.
5783 * 1. foregroundWindow
5784 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5785 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005786TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5788 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005789 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005790
Prabir Pradhanfb549072023-10-05 19:17:36 +00005791 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005792
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005793 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005795 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005796 {100, 200}))
5797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5798
5799 // Both the foreground window and the global monitor should receive the touch down
5800 window->consumeMotionDown();
5801 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5802
5803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005804 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005805 ADISPLAY_ID_DEFAULT, {110, 200}))
5806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5807
5808 window->consumeMotionMove();
5809 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5810
5811 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005812 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005813 window->consumeMotionCancel();
5814 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5815
5816 // If more events come in, there will be no more foreground window to send them to. This will
5817 // cause a cancel for the monitor, as well.
5818 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005819 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005820 ADISPLAY_ID_DEFAULT, {120, 200}))
5821 << "Injection should fail because the window was removed";
5822 window->assertNoEvents();
5823 // Global monitor now gets the cancel
5824 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5825}
5826
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005827TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005829 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5830 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005831 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005832
Prabir Pradhanfb549072023-10-05 19:17:36 +00005833 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005834
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005838 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005839 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005840}
5841
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005842TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005843 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005844
Chris Yea209fde2020-07-22 13:54:51 -07005845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005846 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5847 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005848 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005849
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005851 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005853 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005854 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005855
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005856 // Pilfer pointers from the monitor.
5857 // This should not do anything and the window should continue to receive events.
5858 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005859
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005861 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005862 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005864
5865 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5866 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005867}
5868
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005869TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005871 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5872 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005874 window->setWindowOffset(20, 40);
5875 window->setWindowTransform(0, 1, -1, 0);
5876
Prabir Pradhanfb549072023-10-05 19:17:36 +00005877 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005878
5879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005880 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5882 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5883 MotionEvent* event = monitor.consumeMotion();
5884 // Even though window has transform, gesture monitor must not.
5885 ASSERT_EQ(ui::Transform(), event->getTransform());
5886}
5887
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005888TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005890 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005891
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005892 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005894 << "Injection should fail if there is a monitor, but no touchable window";
5895 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005896}
5897
chaviw81e2bb92019-12-18 15:03:51 -08005898TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005900 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5901 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005902
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005903 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005904
5905 NotifyMotionArgs motionArgs =
5906 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5907 ADISPLAY_ID_DEFAULT);
5908
Prabir Pradhan678438e2023-04-13 19:32:51 +00005909 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005910 // Window should receive motion down event.
5911 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5912
5913 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005914 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005915 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5916 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5917 motionArgs.pointerCoords[0].getX() - 10);
5918
Prabir Pradhan678438e2023-04-13 19:32:51 +00005919 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005920 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005921 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005922}
5923
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005924/**
5925 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5926 * the device default right away. In the test scenario, we check both the default value,
5927 * and the action of enabling / disabling.
5928 */
5929TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005931 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5932 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005933 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005934
5935 // Set focused application.
5936 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005937 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005938
5939 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005940 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005941 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005942 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005943
5944 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005945 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005946 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005947 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005948
5949 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005950 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005951 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005952 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005953 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005954 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005955 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005956 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005957
5958 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005959 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005960 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005961 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005962
5963 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005964 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005965 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005966 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005967 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005968 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005969 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005970 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005971
5972 window->assertNoEvents();
5973}
5974
Gang Wange9087892020-01-07 12:17:14 -05005975TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005976 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005977 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5978 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005979
5980 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005981 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005982
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005983 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005984 setFocusedWindow(window);
5985
Harry Cutts33476232023-01-30 19:57:29 +00005986 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005987
Prabir Pradhan678438e2023-04-13 19:32:51 +00005988 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5989 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005990
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005991 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005992 ASSERT_NE(event, nullptr);
5993
5994 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5995 ASSERT_NE(verified, nullptr);
5996 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5997
5998 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5999 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6000 ASSERT_EQ(keyArgs.source, verified->source);
6001 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6002
6003 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6004
6005 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006006 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006007 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006008 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6009 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6010 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6011 ASSERT_EQ(0, verifiedKey.repeatCount);
6012}
6013
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006014TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006016 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6017 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006018
6019 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6020
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006021 ui::Transform transform;
6022 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6023
6024 gui::DisplayInfo displayInfo;
6025 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6026 displayInfo.transform = transform;
6027
Patrick Williamsd828f302023-04-28 17:52:08 -05006028 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006029
Prabir Pradhan678438e2023-04-13 19:32:51 +00006030 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006031 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6032 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006033 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006034
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006035 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006036 ASSERT_NE(event, nullptr);
6037
6038 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
6039 ASSERT_NE(verified, nullptr);
6040 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6041
6042 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6043 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6044 EXPECT_EQ(motionArgs.source, verified->source);
6045 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6046
6047 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6048
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006049 const vec2 rawXY =
6050 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6051 motionArgs.pointerCoords[0].getXYValue());
6052 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6053 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006054 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006055 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006056 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006057 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6058 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6059}
6060
chaviw09c8d2d2020-08-24 15:48:26 -07006061/**
6062 * Ensure that separate calls to sign the same data are generating the same key.
6063 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6064 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6065 * tests.
6066 */
6067TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6068 KeyEvent event = getTestKeyEvent();
6069 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6070
6071 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6072 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6073 ASSERT_EQ(hmac1, hmac2);
6074}
6075
6076/**
6077 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6078 */
6079TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6080 KeyEvent event = getTestKeyEvent();
6081 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6082 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6083
6084 verifiedEvent.deviceId += 1;
6085 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6086
6087 verifiedEvent.source += 1;
6088 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6089
6090 verifiedEvent.eventTimeNanos += 1;
6091 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6092
6093 verifiedEvent.displayId += 1;
6094 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6095
6096 verifiedEvent.action += 1;
6097 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6098
6099 verifiedEvent.downTimeNanos += 1;
6100 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6101
6102 verifiedEvent.flags += 1;
6103 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6104
6105 verifiedEvent.keyCode += 1;
6106 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6107
6108 verifiedEvent.scanCode += 1;
6109 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6110
6111 verifiedEvent.metaState += 1;
6112 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6113
6114 verifiedEvent.repeatCount += 1;
6115 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6116}
6117
Vishnu Nair958da932020-08-21 17:12:37 -07006118TEST_F(InputDispatcherTest, SetFocusedWindow) {
6119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6120 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006121 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006122 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006123 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006124 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6125
6126 // Top window is also focusable but is not granted focus.
6127 windowTop->setFocusable(true);
6128 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006129 mDispatcher->onWindowInfosChanged(
6130 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006131 setFocusedWindow(windowSecond);
6132
6133 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006135 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006136
6137 // Focused window should receive event.
6138 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6139 windowTop->assertNoEvents();
6140}
6141
6142TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6144 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006145 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006146 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6147
6148 window->setFocusable(true);
6149 // Release channel for window is no longer valid.
6150 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006151 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006152 setFocusedWindow(window);
6153
6154 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006155 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006156
6157 // window channel is invalid, so it should not receive any input event.
6158 window->assertNoEvents();
6159}
6160
6161TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6162 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6163 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006164 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006165 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006166 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6167
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006168 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006169 setFocusedWindow(window);
6170
6171 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006172 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006173
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006174 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006175 window->assertNoEvents();
6176}
6177
6178TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6179 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6180 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006181 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006182 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006183 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006184 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6185
6186 windowTop->setFocusable(true);
6187 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006188 mDispatcher->onWindowInfosChanged(
6189 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006190 setFocusedWindow(windowTop);
6191 windowTop->consumeFocusEvent(true);
6192
Chavi Weingarten847e8512023-03-29 00:26:09 +00006193 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006194 mDispatcher->onWindowInfosChanged(
6195 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006196 windowSecond->consumeFocusEvent(true);
6197 windowTop->consumeFocusEvent(false);
6198
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006200 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006201
6202 // Focused window should receive event.
6203 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6204}
6205
Chavi Weingarten847e8512023-03-29 00:26:09 +00006206TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6208 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006209 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006210 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006211 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006212 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6213
6214 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006215 windowSecond->setFocusable(false);
6216 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006217 mDispatcher->onWindowInfosChanged(
6218 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006219 setFocusedWindow(windowTop);
6220 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006221
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006223 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006224
6225 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006226 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006227 windowSecond->assertNoEvents();
6228}
6229
6230TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6231 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6232 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006233 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006234 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006235 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6236 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006237 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6238
6239 window->setFocusable(true);
6240 previousFocusedWindow->setFocusable(true);
6241 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006242 mDispatcher->onWindowInfosChanged(
6243 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006244 setFocusedWindow(previousFocusedWindow);
6245 previousFocusedWindow->consumeFocusEvent(true);
6246
6247 // Requesting focus on invisible window takes focus from currently focused window.
6248 setFocusedWindow(window);
6249 previousFocusedWindow->consumeFocusEvent(false);
6250
6251 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006253 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6254 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006255
6256 // Window does not get focus event or key down.
6257 window->assertNoEvents();
6258
6259 // Window becomes visible.
6260 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006261 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006262
6263 // Window receives focus event.
6264 window->consumeFocusEvent(true);
6265 // Focused window receives key down.
6266 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6267}
6268
Vishnu Nair599f1412021-06-21 10:39:58 -07006269TEST_F(InputDispatcherTest, DisplayRemoved) {
6270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6271 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006272 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006273 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6274
6275 // window is granted focus.
6276 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006277 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006278 setFocusedWindow(window);
6279 window->consumeFocusEvent(true);
6280
6281 // When a display is removed window loses focus.
6282 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6283 window->consumeFocusEvent(false);
6284}
6285
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006286/**
6287 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6288 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6289 * of the 'slipperyEnterWindow'.
6290 *
6291 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6292 * a way so that the touched location is no longer covered by the top window.
6293 *
6294 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6295 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6296 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6297 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6298 * with ACTION_DOWN).
6299 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6300 * window moved itself away from the touched location and had Flag::SLIPPERY.
6301 *
6302 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6303 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6304 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6305 *
6306 * In this test, we ensure that the event received by the bottom window has
6307 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6308 */
6309TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006310 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006311 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006312
6313 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6314 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6315
6316 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006317 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006318 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006319 // Make sure this one overlaps the bottom window
6320 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6321 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6322 // one. Windows with the same owner are not considered to be occluding each other.
6323 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6324
6325 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006327 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6328
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006329 mDispatcher->onWindowInfosChanged(
6330 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006331
6332 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006333 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6334 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6335 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006336 slipperyExitWindow->consumeMotionDown();
6337 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006338 mDispatcher->onWindowInfosChanged(
6339 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006340
Prabir Pradhan678438e2023-04-13 19:32:51 +00006341 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6342 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6343 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006344
6345 slipperyExitWindow->consumeMotionCancel();
6346
6347 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6348 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6349}
6350
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006351/**
6352 * Two windows, one on the left and another on the right. The left window is slippery. The right
6353 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6354 * touch moves from the left window into the right window, the gesture should continue to go to the
6355 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6356 * reproduces a crash.
6357 */
6358TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6360
6361 sp<FakeWindowHandle> leftSlipperyWindow =
6362 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6363 leftSlipperyWindow->setSlippery(true);
6364 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6365
6366 sp<FakeWindowHandle> rightDropTouchesWindow =
6367 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6368 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6369 rightDropTouchesWindow->setDropInput(true);
6370
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006371 mDispatcher->onWindowInfosChanged(
6372 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006373
6374 // Start touch in the left window
6375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6376 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6377 .build());
6378 leftSlipperyWindow->consumeMotionDown();
6379
6380 // And move it into the right window
6381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6382 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6383 .build());
6384
6385 // Since the right window isn't eligible to receive input, touch does not slip.
6386 // The left window continues to receive the gesture.
6387 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6388 rightDropTouchesWindow->assertNoEvents();
6389}
6390
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006391/**
6392 * A single window is on screen first. Touch is injected into that window. Next, a second window
6393 * appears. Since the first window is slippery, touch will move from the first window to the second.
6394 */
6395TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6397 sp<FakeWindowHandle> originalWindow =
6398 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6399 originalWindow->setFrame(Rect(0, 0, 200, 200));
6400 originalWindow->setSlippery(true);
6401
6402 sp<FakeWindowHandle> appearingWindow =
6403 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6404 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6405
6406 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6407
6408 // Touch down on the original window
6409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6410 injectMotionEvent(*mDispatcher,
6411 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6412 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6413 .build()));
6414 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6415
6416 // Now, a new window appears. This could be, for example, a notification shade that appears
6417 // after user starts to drag down on the launcher window.
6418 mDispatcher->onWindowInfosChanged(
6419 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6421 injectMotionEvent(*mDispatcher,
6422 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6423 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6424 .build()));
6425 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6426 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6428 injectMotionEvent(*mDispatcher,
6429 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6430 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6431 .build()));
6432 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6433
6434 originalWindow->assertNoEvents();
6435 appearingWindow->assertNoEvents();
6436}
6437
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006438TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006439 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6441
6442 sp<FakeWindowHandle> leftWindow =
6443 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6444 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006445 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006446
6447 sp<FakeWindowHandle> rightSpy =
6448 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6449 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006450 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006451 rightSpy->setSpy(true);
6452 rightSpy->setTrustedOverlay(true);
6453
6454 sp<FakeWindowHandle> rightWindow =
6455 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6456 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006457 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006459 mDispatcher->onWindowInfosChanged(
6460 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006461
6462 // Touch in the left window
6463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6464 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6465 .build());
6466 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6467 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006468 ASSERT_NO_FATAL_FAILURE(
6469 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006470
6471 // Touch another finger over the right windows
6472 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6473 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6474 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6475 .build());
6476 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6477 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6478 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6479 mDispatcher->waitForIdle();
6480 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006481 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6482 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006483
6484 // Release finger over left window. The UP actions are not treated as device interaction.
6485 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6486 // is part of the UP action, we do not treat this as device interaction.
6487 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6488 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6489 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6490 .build());
6491 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6492 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6493 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6494 mDispatcher->waitForIdle();
6495 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6496
6497 // Move remaining finger
6498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6499 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6500 .build());
6501 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6502 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6503 mDispatcher->waitForIdle();
6504 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006505 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006506
6507 // Release all fingers
6508 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6509 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6510 .build());
6511 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6512 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6513 mDispatcher->waitForIdle();
6514 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6515}
6516
6517TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6519
6520 sp<FakeWindowHandle> window =
6521 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6522 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006523 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006524
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006525 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006526 setFocusedWindow(window);
6527 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6528
6529 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6530 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6531 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006532 ASSERT_NO_FATAL_FAILURE(
6533 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006534
6535 // The UP actions are not treated as device interaction.
6536 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6537 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6538 mDispatcher->waitForIdle();
6539 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6540}
6541
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006542class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6543protected:
6544 std::shared_ptr<FakeApplicationHandle> mApp;
6545 sp<FakeWindowHandle> mWindow;
6546
6547 virtual void SetUp() override {
6548 InputDispatcherTest::SetUp();
6549
6550 mApp = std::make_shared<FakeApplicationHandle>();
6551
6552 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6553 mWindow->setFrame(Rect(0, 0, 100, 100));
6554
6555 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6556 setFocusedWindow(mWindow);
6557 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6558 }
6559
6560 void setFallback(int32_t keycode) {
6561 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6562 return KeyEventBuilder(event).keyCode(keycode).build();
6563 });
6564 }
6565
6566 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
6567 KeyEvent* event = mWindow->consumeKey(handled);
6568 ASSERT_NE(event, nullptr) << "Did not receive key event";
6569 ASSERT_THAT(*event, matcher);
6570 }
6571};
6572
6573TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6574 mDispatcher->notifyKey(
6575 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6576 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6577 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6578}
6579
6580TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6581 mDispatcher->notifyKey(
6582 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6583 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6584 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6585}
6586
6587TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6588 mDispatcher->notifyKey(
6589 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6590
6591 // Do not handle this key event.
6592 consumeKey(/*handled=*/false,
6593 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6594 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6595
6596 // Since the policy did not request any fallback to be generated, ensure there are no events.
6597 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6598}
6599
6600TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6601 setFallback(AKEYCODE_B);
6602 mDispatcher->notifyKey(
6603 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6604
6605 // Do not handle this key event.
6606 consumeKey(/*handled=*/false,
6607 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6608
6609 // Since the key was not handled, ensure the fallback event was dispatched instead.
6610 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6611 consumeKey(/*handled=*/true,
6612 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6613 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6614
6615 // Release the original key, and ensure the fallback key is also released.
6616 mDispatcher->notifyKey(
6617 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6618 consumeKey(/*handled=*/false,
6619 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6620 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6621 consumeKey(/*handled=*/true,
6622 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6623 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6624
6625 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6626 mWindow->assertNoEvents();
6627}
6628
6629TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6630 setFallback(AKEYCODE_B);
6631 mDispatcher->notifyKey(
6632 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6633
6634 // Do not handle this key event, but handle the fallback.
6635 consumeKey(/*handled=*/false,
6636 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6637 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6638 consumeKey(/*handled=*/true,
6639 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6640 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6641
6642 // Release the original key, and ensure the fallback key is also released.
6643 mDispatcher->notifyKey(
6644 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6645 // But this time, the app handles the original key.
6646 consumeKey(/*handled=*/true,
6647 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6648 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6649 // Ensure the fallback key is canceled.
6650 consumeKey(/*handled=*/true,
6651 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6652 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6653
6654 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6655 mWindow->assertNoEvents();
6656}
6657
6658TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6659 setFallback(AKEYCODE_B);
6660 mDispatcher->notifyKey(
6661 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6662
6663 // Do not handle this key event.
6664 consumeKey(/*handled=*/false,
6665 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6666 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6667 // App does not handle the fallback either, so ensure another fallback is not generated.
6668 setFallback(AKEYCODE_C);
6669 consumeKey(/*handled=*/false,
6670 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6671 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6672
6673 // Release the original key, and ensure the fallback key is also released.
6674 setFallback(AKEYCODE_B);
6675 mDispatcher->notifyKey(
6676 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6677 consumeKey(/*handled=*/false,
6678 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6679 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6680 consumeKey(/*handled=*/false,
6681 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6682 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6683
6684 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6685 mWindow->assertNoEvents();
6686}
6687
6688TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6689 setFallback(AKEYCODE_B);
6690 mDispatcher->notifyKey(
6691 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6692
6693 // Do not handle this key event, so fallback is generated.
6694 consumeKey(/*handled=*/false,
6695 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6696 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6697 consumeKey(/*handled=*/true,
6698 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6699 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6700
6701 // Release the original key, but assume the policy is misbehaving and it
6702 // generates an inconsistent fallback to the one from the DOWN event.
6703 setFallback(AKEYCODE_C);
6704 mDispatcher->notifyKey(
6705 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6706 consumeKey(/*handled=*/false,
6707 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6708 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6709 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6710 consumeKey(/*handled=*/true,
6711 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6712 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6713
6714 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6715 mWindow->assertNoEvents();
6716}
6717
6718TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6719 setFallback(AKEYCODE_B);
6720 mDispatcher->notifyKey(
6721 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6722
6723 // Do not handle this key event, so fallback is generated.
6724 consumeKey(/*handled=*/false,
6725 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6726 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6727 consumeKey(/*handled=*/true,
6728 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6729 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6730
6731 // The original key is canceled.
6732 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6733 .keyCode(AKEYCODE_A)
6734 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6735 .build());
6736 consumeKey(/*handled=*/false,
6737 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6738 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6739 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6740 // Ensure the fallback key is also canceled due to the original key being canceled.
6741 consumeKey(/*handled=*/true,
6742 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6743 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6744
6745 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6746 mWindow->assertNoEvents();
6747}
6748
Garfield Tan1c7bc862020-01-28 13:24:04 -08006749class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6750protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006751 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6752 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006753
Chris Yea209fde2020-07-22 13:54:51 -07006754 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006755 sp<FakeWindowHandle> mWindow;
6756
6757 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006758 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006759 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006760 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006761 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006762 ASSERT_EQ(OK, mDispatcher->start());
6763
6764 setUpWindow();
6765 }
6766
6767 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006768 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006769 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006770
Vishnu Nair47074b82020-08-14 11:54:47 -07006771 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006772 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006773 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006774 mWindow->consumeFocusEvent(true);
6775 }
6776
Chris Ye2ad95392020-09-01 13:44:44 -07006777 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006778 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006779 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006780 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006781 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006782
6783 // Window should receive key down event.
6784 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6785 }
6786
6787 void expectKeyRepeatOnce(int32_t repeatCount) {
6788 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006789 mWindow->consumeKeyEvent(
6790 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006791 }
6792
Chris Ye2ad95392020-09-01 13:44:44 -07006793 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006794 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006795 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006796 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006797 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006798
6799 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006800 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006801 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006802 }
6803};
6804
6805TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006806 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006807 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6808 expectKeyRepeatOnce(repeatCount);
6809 }
6810}
6811
6812TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006813 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006814 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6815 expectKeyRepeatOnce(repeatCount);
6816 }
Harry Cutts33476232023-01-30 19:57:29 +00006817 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006818 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006819 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6820 expectKeyRepeatOnce(repeatCount);
6821 }
6822}
6823
6824TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006825 sendAndConsumeKeyDown(/*deviceId=*/1);
6826 expectKeyRepeatOnce(/*repeatCount=*/1);
6827 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006828 mWindow->assertNoEvents();
6829}
6830
6831TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006832 sendAndConsumeKeyDown(/*deviceId=*/1);
6833 expectKeyRepeatOnce(/*repeatCount=*/1);
6834 sendAndConsumeKeyDown(/*deviceId=*/2);
6835 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006836 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006837 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006838 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006839 expectKeyRepeatOnce(/*repeatCount=*/2);
6840 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006841 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006842 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006843 mWindow->assertNoEvents();
6844}
6845
6846TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006847 sendAndConsumeKeyDown(/*deviceId=*/1);
6848 expectKeyRepeatOnce(/*repeatCount=*/1);
6849 sendAndConsumeKeyDown(/*deviceId=*/2);
6850 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006851 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006852 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006853 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006854 mWindow->assertNoEvents();
6855}
6856
liushenxiang42232912021-05-21 20:24:09 +08006857TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6858 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006859 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006860 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006861 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6862 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6863 mWindow->assertNoEvents();
6864}
6865
Garfield Tan1c7bc862020-01-28 13:24:04 -08006866TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006867 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006868 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006869 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006870 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006871 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6872 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6873 IdGenerator::getSource(repeatEvent->getId()));
6874 }
6875}
6876
6877TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006878 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006879 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006880
6881 std::unordered_set<int32_t> idSet;
6882 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006883 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006884 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6885 int32_t id = repeatEvent->getId();
6886 EXPECT_EQ(idSet.end(), idSet.find(id));
6887 idSet.insert(id);
6888 }
6889}
6890
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006891/* Test InputDispatcher for MultiDisplay */
6892class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6893public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006894 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006895 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006896
Chris Yea209fde2020-07-22 13:54:51 -07006897 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006898 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006899 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006900
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006901 // Set focus window for primary display, but focused display would be second one.
6902 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006903 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006904 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6905
Vishnu Nair958da932020-08-21 17:12:37 -07006906 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006907 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006908
Chris Yea209fde2020-07-22 13:54:51 -07006909 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006910 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006911 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006912 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006913 // Set focus display to second one.
6914 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6915 // Set focus window for second display.
6916 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006917 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006918 mDispatcher->onWindowInfosChanged(
6919 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006920 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006921 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006922 }
6923
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006924 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006925 InputDispatcherTest::TearDown();
6926
Chris Yea209fde2020-07-22 13:54:51 -07006927 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006928 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006929 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006930 windowInSecondary.clear();
6931 }
6932
6933protected:
Chris Yea209fde2020-07-22 13:54:51 -07006934 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006935 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006936 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006937 sp<FakeWindowHandle> windowInSecondary;
6938};
6939
6940TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6941 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006943 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006945 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006946 windowInSecondary->assertNoEvents();
6947
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006948 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006950 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006952 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006953 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006954}
6955
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006956TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006957 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006959 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006960 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006961 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006962 windowInSecondary->assertNoEvents();
6963
6964 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006966 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006967 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006968 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006969
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006970 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006971 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006972
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006973 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006974 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006975 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006976
6977 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006978 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006979 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006980 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006981 windowInSecondary->assertNoEvents();
6982}
6983
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006984// Test per-display input monitors for motion event.
6985TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006986 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006987 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006988 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006989 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006990
6991 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006993 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006995 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006996 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006997 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006998 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006999
7000 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007002 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007004 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007005 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007006 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007007 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007008
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007009 // Lift up the touch from the second display
7010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007011 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7013 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7014 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7015
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007016 // Test inject a non-pointer motion event.
7017 // If specific a display, it will dispatch to the focused window of particular display,
7018 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007020 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007022 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007023 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007024 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007025 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007026}
7027
7028// Test per-display input monitors for key event.
7029TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007030 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007031 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007032 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007033 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007034 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007035
7036 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007038 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007039 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007040 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007041 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007042 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007043}
7044
Vishnu Nair958da932020-08-21 17:12:37 -07007045TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7046 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007047 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007048 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007049 mDispatcher->onWindowInfosChanged(
7050 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7051 *windowInSecondary->getInfo()},
7052 {},
7053 0,
7054 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007055 setFocusedWindow(secondWindowInPrimary);
7056 windowInPrimary->consumeFocusEvent(false);
7057 secondWindowInPrimary->consumeFocusEvent(true);
7058
7059 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7061 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007062 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007063 windowInPrimary->assertNoEvents();
7064 windowInSecondary->assertNoEvents();
7065 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7066}
7067
Arthur Hungdfd528e2021-12-08 13:23:04 +00007068TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7069 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007070 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007071 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007072 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007073
7074 // Test touch down on primary display.
7075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7078 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7079 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7080
7081 // Test touch down on second display.
7082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007083 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7085 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7086 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7087
7088 // Trigger cancel touch.
7089 mDispatcher->cancelCurrentTouch();
7090 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7091 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7092 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7093 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7094
7095 // Test inject a move motion event, no window/monitor should receive the event.
7096 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007097 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007098 ADISPLAY_ID_DEFAULT, {110, 200}))
7099 << "Inject motion event should return InputEventInjectionResult::FAILED";
7100 windowInPrimary->assertNoEvents();
7101 monitorInPrimary.assertNoEvents();
7102
7103 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007104 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007105 SECOND_DISPLAY_ID, {110, 200}))
7106 << "Inject motion event should return InputEventInjectionResult::FAILED";
7107 windowInSecondary->assertNoEvents();
7108 monitorInSecondary.assertNoEvents();
7109}
7110
Jackal Guof9696682018-10-05 12:23:23 +08007111class InputFilterTest : public InputDispatcherTest {
7112protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007113 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7114 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007115 NotifyMotionArgs motionArgs;
7116
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007117 motionArgs =
7118 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007119 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007120 motionArgs =
7121 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007122 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007123 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007124 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007125 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007126 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007127 } else {
7128 mFakePolicy->assertFilterInputEventWasNotCalled();
7129 }
7130 }
7131
7132 void testNotifyKey(bool expectToBeFiltered) {
7133 NotifyKeyArgs keyArgs;
7134
7135 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007136 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007137 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007138 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007139 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007140
7141 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007142 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007143 } else {
7144 mFakePolicy->assertFilterInputEventWasNotCalled();
7145 }
7146 }
7147};
7148
7149// Test InputFilter for MotionEvent
7150TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7151 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007152 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7153 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007154
7155 // Enable InputFilter
7156 mDispatcher->setInputFilterEnabled(true);
7157 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007158 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7159 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007160
7161 // Disable InputFilter
7162 mDispatcher->setInputFilterEnabled(false);
7163 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007164 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7165 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007166}
7167
7168// Test InputFilter for KeyEvent
7169TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7170 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007171 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007172
7173 // Enable InputFilter
7174 mDispatcher->setInputFilterEnabled(true);
7175 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007176 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007177
7178 // Disable InputFilter
7179 mDispatcher->setInputFilterEnabled(false);
7180 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007181 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007182}
7183
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007184// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7185// logical display coordinate space.
7186TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7187 ui::Transform firstDisplayTransform;
7188 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7189 ui::Transform secondDisplayTransform;
7190 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7191
7192 std::vector<gui::DisplayInfo> displayInfos(2);
7193 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7194 displayInfos[0].transform = firstDisplayTransform;
7195 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7196 displayInfos[1].transform = secondDisplayTransform;
7197
Patrick Williamsd828f302023-04-28 17:52:08 -05007198 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007199
7200 // Enable InputFilter
7201 mDispatcher->setInputFilterEnabled(true);
7202
7203 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007204 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7205 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007206}
7207
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007208class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7209protected:
7210 virtual void SetUp() override {
7211 InputDispatcherTest::SetUp();
7212
7213 /**
7214 * We don't need to enable input filter to test the injected event policy, but we enabled it
7215 * here to make the tests more realistic, since this policy only matters when inputfilter is
7216 * on.
7217 */
7218 mDispatcher->setInputFilterEnabled(true);
7219
7220 std::shared_ptr<InputApplicationHandle> application =
7221 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007222 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7223 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007224
7225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7226 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007227 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007228 setFocusedWindow(mWindow);
7229 mWindow->consumeFocusEvent(true);
7230 }
7231
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007232 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7233 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007234 KeyEvent event;
7235
7236 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7237 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7238 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007239 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007240 const int32_t additionalPolicyFlags =
7241 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007243 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007244 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007245 policyFlags | additionalPolicyFlags));
7246
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007247 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007248 }
7249
7250 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7251 int32_t flags) {
7252 MotionEvent event;
7253 PointerProperties pointerProperties[1];
7254 PointerCoords pointerCoords[1];
7255 pointerProperties[0].clear();
7256 pointerProperties[0].id = 0;
7257 pointerCoords[0].clear();
7258 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7259 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7260
7261 ui::Transform identityTransform;
7262 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7263 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7264 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7265 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7266 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007267 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007268 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007269 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007270
7271 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007273 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007274 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007275 policyFlags | additionalPolicyFlags));
7276
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007277 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007278 }
7279
7280private:
7281 sp<FakeWindowHandle> mWindow;
7282};
7283
7284TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007285 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7286 // filter. Without it, the event will no different from a regularly injected event, and the
7287 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007288 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7289 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007290}
7291
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007292TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007293 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007294 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007295 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7296}
7297
7298TEST_F(InputFilterInjectionPolicyTest,
7299 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7300 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007301 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007302 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007303}
7304
7305TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007306 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7307 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007308}
7309
chaviwfd6d3512019-03-25 13:23:49 -07007310class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007311 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007312 InputDispatcherTest::SetUp();
7313
Chris Yea209fde2020-07-22 13:54:51 -07007314 std::shared_ptr<FakeApplicationHandle> application =
7315 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007316 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007317 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007318 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007319
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007320 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007321 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007322 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007323
7324 // Set focused application.
7325 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007326 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007327
7328 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007329 mDispatcher->onWindowInfosChanged(
7330 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007331 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007332 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007333 }
7334
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007335 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007336 InputDispatcherTest::TearDown();
7337
7338 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007339 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007340 }
7341
7342protected:
7343 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007344 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007345 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007346};
7347
7348// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7349// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7350// the onPointerDownOutsideFocus callback.
7351TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007353 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007354 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007356 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007357
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007358 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007359 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7360}
7361
7362// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7363// DOWN on the window that doesn't have focus. Ensure no window received the
7364// onPointerDownOutsideFocus callback.
7365TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007367 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7368 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007370 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007371
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007372 ASSERT_TRUE(mDispatcher->waitForIdle());
7373 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007374}
7375
7376// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7377// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7378TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007380 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007381 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007382 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007383
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007384 ASSERT_TRUE(mDispatcher->waitForIdle());
7385 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007386}
7387
7388// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7389// DOWN on the window that already has focus. Ensure no window received the
7390// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007391TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007393 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007394 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007395 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007396 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007397
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007398 ASSERT_TRUE(mDispatcher->waitForIdle());
7399 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007400}
7401
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007402// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7403// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7404TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7405 const MotionEvent event =
7406 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7407 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007408 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007409 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7410 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007412 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7413 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7414
7415 ASSERT_TRUE(mDispatcher->waitForIdle());
7416 mFakePolicy->assertOnPointerDownWasNotCalled();
7417 // Ensure that the unfocused window did not receive any FOCUS events.
7418 mUnfocusedWindow->assertNoEvents();
7419}
7420
chaviwaf87b3e2019-10-01 16:59:28 -07007421// These tests ensures we can send touch events to a single client when there are multiple input
7422// windows that point to the same client token.
7423class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7424 virtual void SetUp() override {
7425 InputDispatcherTest::SetUp();
7426
Chris Yea209fde2020-07-22 13:54:51 -07007427 std::shared_ptr<FakeApplicationHandle> application =
7428 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007429 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7430 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007431 mWindow1->setFrame(Rect(0, 0, 100, 100));
7432
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007433 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7434 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007435 mWindow2->setFrame(Rect(100, 100, 200, 200));
7436
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007437 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007438 }
7439
7440protected:
7441 sp<FakeWindowHandle> mWindow1;
7442 sp<FakeWindowHandle> mWindow2;
7443
7444 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007445 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007446 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7447 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007448 }
7449
7450 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7451 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007452 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007453 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007454
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007455 ASSERT_NE(nullptr, motionEvent)
7456 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007457
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007458 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007459 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007460
7461 for (size_t i = 0; i < points.size(); i++) {
7462 float expectedX = points[i].x;
7463 float expectedY = points[i].y;
7464
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007465 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007466 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007467 << ", got " << motionEvent->getX(i);
7468 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007469 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007470 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007471 }
7472 }
chaviw9eaa22c2020-07-01 16:21:27 -07007473
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007474 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007475 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007476 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7477 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007478
7479 // Always consume from window1 since it's the window that has the InputReceiver
7480 consumeMotionEvent(mWindow1, action, expectedPoints);
7481 }
chaviwaf87b3e2019-10-01 16:59:28 -07007482};
7483
7484TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7485 // Touch Window 1
7486 PointF touchedPoint = {10, 10};
7487 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007488 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007489
7490 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007491 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007492
7493 // Touch Window 2
7494 touchedPoint = {150, 150};
7495 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007496 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007497}
7498
chaviw9eaa22c2020-07-01 16:21:27 -07007499TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7500 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007501 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007502 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007503
7504 // Touch Window 1
7505 PointF touchedPoint = {10, 10};
7506 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007507 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007508 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007509 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007510
7511 // Touch Window 2
7512 touchedPoint = {150, 150};
7513 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007514 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7515 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007516
chaviw9eaa22c2020-07-01 16:21:27 -07007517 // Update the transform so rotation is set
7518 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007519 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007520 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7521 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007522}
7523
chaviw9eaa22c2020-07-01 16:21:27 -07007524TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007525 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007526 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007527
7528 // Touch Window 1
7529 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7530 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007531 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007532
7533 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007534 touchedPoints.push_back(PointF{150, 150});
7535 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007536 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007537
chaviw9eaa22c2020-07-01 16:21:27 -07007538 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007539 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007540 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007541
chaviw9eaa22c2020-07-01 16:21:27 -07007542 // Update the transform so rotation is set for Window 2
7543 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007544 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007545 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007546 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007547}
7548
chaviw9eaa22c2020-07-01 16:21:27 -07007549TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007550 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007551 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007552
7553 // Touch Window 1
7554 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7555 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007556 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007557
7558 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007559 touchedPoints.push_back(PointF{150, 150});
7560 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007561
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007562 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007563
7564 // Move both windows
7565 touchedPoints = {{20, 20}, {175, 175}};
7566 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7567 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7568
chaviw9eaa22c2020-07-01 16:21:27 -07007569 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007570
chaviw9eaa22c2020-07-01 16:21:27 -07007571 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007572 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007573 expectedPoints.pop_back();
7574
7575 // Touch Window 2
7576 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007577 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007578 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007579 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007580
7581 // Move both windows
7582 touchedPoints = {{20, 20}, {175, 175}};
7583 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7584 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7585
7586 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007587}
7588
7589TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7590 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007591 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007592
7593 // Touch Window 1
7594 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7595 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007596 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007597
7598 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007599 touchedPoints.push_back(PointF{150, 150});
7600 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007601
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007602 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007603
7604 // Move both windows
7605 touchedPoints = {{20, 20}, {175, 175}};
7606 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7607 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7608
chaviw9eaa22c2020-07-01 16:21:27 -07007609 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007610}
7611
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007612/**
7613 * When one of the windows is slippery, the touch should not slip into the other window with the
7614 * same input channel.
7615 */
7616TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7617 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007618 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007619
7620 // Touch down in window 1
7621 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7622 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7623 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7624
7625 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7626 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7627 // getting generated.
7628 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7629 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7630
7631 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7632}
7633
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007634/**
7635 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7636 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7637 * that the pointer is hovering over may have a different transform.
7638 */
7639TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007640 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007641
7642 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7645 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007646 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7647 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007648 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7650 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7651 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007652 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7653 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7654 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7655}
7656
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007657class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7658 virtual void SetUp() override {
7659 InputDispatcherTest::SetUp();
7660
Chris Yea209fde2020-07-22 13:54:51 -07007661 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007662 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007663 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7664 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007665 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007666 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007667 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007668
7669 // Set focused application.
7670 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7671
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007672 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007673 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007674 mWindow->consumeFocusEvent(true);
7675 }
7676
7677 virtual void TearDown() override {
7678 InputDispatcherTest::TearDown();
7679 mWindow.clear();
7680 }
7681
7682protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007683 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007684 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007685 sp<FakeWindowHandle> mWindow;
7686 static constexpr PointF WINDOW_LOCATION = {20, 20};
7687
7688 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007690 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007691 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007693 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007694 WINDOW_LOCATION));
7695 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007696
7697 sp<FakeWindowHandle> addSpyWindow() {
7698 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007699 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007700 spy->setTrustedOverlay(true);
7701 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007702 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007703 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007704 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007705 return spy;
7706 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007707};
7708
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007709// Send a tap and respond, which should not cause an ANR.
7710TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7711 tapOnWindow();
7712 mWindow->consumeMotionDown();
7713 mWindow->consumeMotionUp();
7714 ASSERT_TRUE(mDispatcher->waitForIdle());
7715 mFakePolicy->assertNotifyAnrWasNotCalled();
7716}
7717
7718// Send a regular key and respond, which should not cause an ANR.
7719TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007721 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7722 ASSERT_TRUE(mDispatcher->waitForIdle());
7723 mFakePolicy->assertNotifyAnrWasNotCalled();
7724}
7725
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007726TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7727 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007728 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007729 mWindow->consumeFocusEvent(false);
7730
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007731 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007732 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7733 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007734 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007736 // Key will not go to window because we have no focused window.
7737 // The 'no focused window' ANR timer should start instead.
7738
7739 // Now, the focused application goes away.
7740 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7741 // The key should get dropped and there should be no ANR.
7742
7743 ASSERT_TRUE(mDispatcher->waitForIdle());
7744 mFakePolicy->assertNotifyAnrWasNotCalled();
7745}
7746
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007747// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007748// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7749// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007750TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007752 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007753 WINDOW_LOCATION));
7754
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007755 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7756 ASSERT_TRUE(sequenceNum);
7757 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007758 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007759
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007760 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007761 mWindow->consumeMotionEvent(
7762 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007763 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007764 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007765}
7766
7767// Send a key to the app and have the app not respond right away.
7768TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7769 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007771 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7772 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007773 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007774 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007775 ASSERT_TRUE(mDispatcher->waitForIdle());
7776}
7777
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007778// We have a focused application, but no focused window
7779TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007780 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007781 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007782 mWindow->consumeFocusEvent(false);
7783
7784 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007786 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007787 WINDOW_LOCATION));
7788 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7789 mDispatcher->waitForIdle();
7790 mFakePolicy->assertNotifyAnrWasNotCalled();
7791
7792 // Once a focused event arrives, we get an ANR for this application
7793 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7794 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007795 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007796 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007797 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007798 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007799 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007800 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007801 ASSERT_TRUE(mDispatcher->waitForIdle());
7802}
7803
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007804/**
7805 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7806 * there will not be an ANR.
7807 */
7808TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7809 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007810 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007811 mWindow->consumeFocusEvent(false);
7812
7813 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07007814 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
7815 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007816 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7817 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7818
7819 // Define a valid key down event that is stale (too old).
7820 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007821 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007822 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007823
7824 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7825
7826 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007827 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007828 InputEventInjectionSync::WAIT_FOR_RESULT,
7829 INJECT_EVENT_TIMEOUT, policyFlags);
7830 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7831 << "Injection should fail because the event is stale";
7832
7833 ASSERT_TRUE(mDispatcher->waitForIdle());
7834 mFakePolicy->assertNotifyAnrWasNotCalled();
7835 mWindow->assertNoEvents();
7836}
7837
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007838// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007839// Make sure that we don't notify policy twice about the same ANR.
7840TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007841 const std::chrono::duration appTimeout = 400ms;
7842 mApplication->setDispatchingTimeout(appTimeout);
7843 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7844
Vishnu Nair47074b82020-08-14 11:54:47 -07007845 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007846 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007847 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007848
7849 // Once a focused event arrives, we get an ANR for this application
7850 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7851 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007852 const std::chrono::duration eventInjectionTimeout = 100ms;
7853 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007854 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007855 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007856 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7857 /*allowKeyRepeat=*/false);
7858 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7859 << "result=" << ftl::enum_string(result);
7860 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7861 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7862 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7863 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007864
Vishnu Naire4df8752022-09-08 09:17:55 -07007865 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007866 // ANR should not be raised again. It is up to policy to do that if it desires.
7867 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007868
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007869 // If we now get a focused window, the ANR should stop, but the policy handles that via
7870 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007871 ASSERT_TRUE(mDispatcher->waitForIdle());
7872}
7873
7874// We have a focused application, but no focused window
7875TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007876 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007877 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007878 mWindow->consumeFocusEvent(false);
7879
7880 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007881 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007882
Vishnu Naire4df8752022-09-08 09:17:55 -07007883 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7884 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007885
7886 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007887 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007888 ASSERT_TRUE(mDispatcher->waitForIdle());
7889 mWindow->assertNoEvents();
7890}
7891
7892/**
7893 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7894 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7895 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7896 * the ANR mechanism should still work.
7897 *
7898 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7899 * DOWN event, while not responding on the second one.
7900 */
7901TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7902 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007903 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007904 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7905 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7906 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007907 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007908
7909 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007910 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007911 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7912 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7913 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007914 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007915
7916 // We have now sent down and up. Let's consume first event and then ANR on the second.
7917 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7918 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007919 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007920}
7921
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007922// A spy window can receive an ANR
7923TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7924 sp<FakeWindowHandle> spy = addSpyWindow();
7925
7926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007927 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007928 WINDOW_LOCATION));
7929 mWindow->consumeMotionDown();
7930
7931 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7932 ASSERT_TRUE(sequenceNum);
7933 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007934 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007935
7936 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007937 spy->consumeMotionEvent(
7938 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007939 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007940 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007941}
7942
7943// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007944// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007945TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7946 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007947
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007949 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007950 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007952
7953 // Stuck on the ACTION_UP
7954 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007955 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007956
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007957 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007958 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007959 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7960 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007961
7962 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7963 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007964 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007965 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007966 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007967}
7968
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007969// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007970// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007971TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7972 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007973
7974 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007975 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7976 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007977
7978 mWindow->consumeMotionDown();
7979 // Stuck on the ACTION_UP
7980 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007981 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007982
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007983 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007984 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007985 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7986 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007987
7988 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7989 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007990 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007991 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007992 spy->assertNoEvents();
7993}
7994
7995TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007996 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007997
Prabir Pradhanfb549072023-10-05 19:17:36 +00007998 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007999
8000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008001 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008002 WINDOW_LOCATION));
8003
8004 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8005 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8006 ASSERT_TRUE(consumeSeq);
8007
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008008 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8009 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008010
8011 monitor.finishEvent(*consumeSeq);
8012 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8013
8014 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008015 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008016}
8017
8018// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8019// process events, you don't get an anr. When the window later becomes unresponsive again, you
8020// get an ANR again.
8021// 1. tap -> block on ACTION_UP -> receive ANR
8022// 2. consume all pending events (= queue becomes healthy again)
8023// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8024TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8025 tapOnWindow();
8026
8027 mWindow->consumeMotionDown();
8028 // Block on ACTION_UP
8029 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008030 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008031 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8032 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008033 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008034 mWindow->assertNoEvents();
8035
8036 tapOnWindow();
8037 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008038 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008039 mWindow->consumeMotionUp();
8040
8041 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008042 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008043 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008044 mWindow->assertNoEvents();
8045}
8046
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008047// If a connection remains unresponsive for a while, make sure policy is only notified once about
8048// it.
8049TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008051 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008052 WINDOW_LOCATION));
8053
8054 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008055 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008056 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008057 // 'notifyConnectionUnresponsive' should only be called once per connection
8058 mFakePolicy->assertNotifyAnrWasNotCalled();
8059 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008060 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008061 mWindow->consumeMotionEvent(
8062 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008063 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008064 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008065 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008066 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008067}
8068
8069/**
8070 * 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 -07008071 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008072 *
8073 * Warning!!!
8074 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8075 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008076 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008077 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8078 *
8079 * If that value changes, this test should also change.
8080 */
8081TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8082 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008083 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008084
8085 tapOnWindow();
8086 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8087 ASSERT_TRUE(downSequenceNum);
8088 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8089 ASSERT_TRUE(upSequenceNum);
8090 // Don't finish the events yet, and send a key
8091 // Injection will "succeed" because we will eventually give up and send the key to the focused
8092 // window even if motions are still being processed. But because the injection timeout is short,
8093 // we will receive INJECTION_TIMED_OUT as the result.
8094
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008095 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008096 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8097 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008098 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008099 // Key will not be sent to the window, yet, because the window is still processing events
8100 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008101 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8102 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8103 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8104 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008105
8106 std::this_thread::sleep_for(500ms);
8107 // if we wait long enough though, dispatcher will give up, and still send the key
8108 // to the focused window, even though we have not yet finished the motion event
8109 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8110 mWindow->finishEvent(*downSequenceNum);
8111 mWindow->finishEvent(*upSequenceNum);
8112}
8113
8114/**
8115 * If a window is processing a motion event, and then a key event comes in, the key event should
8116 * not go to the focused window until the motion is processed.
8117 * If then a new motion comes in, then the pending key event should be going to the currently
8118 * focused window right away.
8119 */
8120TEST_F(InputDispatcherSingleWindowAnr,
8121 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8122 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008123 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008124
8125 tapOnWindow();
8126 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8127 ASSERT_TRUE(downSequenceNum);
8128 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8129 ASSERT_TRUE(upSequenceNum);
8130 // Don't finish the events yet, and send a key
8131 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008133 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008134 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE, INJECT_EVENT_TIMEOUT,
8135 /*allowKeyRepeat=*/false));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008136 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008137 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8138 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8139 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8140 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008141
8142 // Now tap down again. It should cause the pending key to go to the focused window right away.
8143 tapOnWindow();
8144 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
8145 // the other events yet. We can finish events in any order.
8146 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8147 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
8148 mWindow->consumeMotionDown();
8149 mWindow->consumeMotionUp();
8150 mWindow->assertNoEvents();
8151}
8152
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008153/**
8154 * Send an event to the app and have the app not respond right away.
8155 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8156 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8157 * At some point, the window becomes responsive again.
8158 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8159 */
8160TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8162 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8163 .build());
8164
8165 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8166 ASSERT_TRUE(sequenceNum);
8167 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8168 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8169
8170 mWindow->finishEvent(*sequenceNum);
8171 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8172 ASSERT_TRUE(mDispatcher->waitForIdle());
8173 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8174
8175 // Now that the window is responsive, let's continue the gesture.
8176 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8177 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8178 .build());
8179
8180 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8181 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8182 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8183 .build());
8184
8185 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8186 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8187 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8188 .build());
8189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8190 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8191 .build());
8192 // We already canceled this pointer, so the window shouldn't get any new events.
8193 mWindow->assertNoEvents();
8194
8195 // Start another one.
8196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8197 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8198 .build());
8199 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8200}
8201
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008202class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8203 virtual void SetUp() override {
8204 InputDispatcherTest::SetUp();
8205
Chris Yea209fde2020-07-22 13:54:51 -07008206 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008207 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008208 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8209 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008210 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008211 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008212 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008213
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008214 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8215 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008216 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008217 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008218
8219 // Set focused application.
8220 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008221 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008222
8223 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008224 mDispatcher->onWindowInfosChanged(
8225 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008226 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008227 mFocusedWindow->consumeFocusEvent(true);
8228 }
8229
8230 virtual void TearDown() override {
8231 InputDispatcherTest::TearDown();
8232
8233 mUnfocusedWindow.clear();
8234 mFocusedWindow.clear();
8235 }
8236
8237protected:
Chris Yea209fde2020-07-22 13:54:51 -07008238 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008239 sp<FakeWindowHandle> mUnfocusedWindow;
8240 sp<FakeWindowHandle> mFocusedWindow;
8241 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8242 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8243 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8244
8245 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8246
8247 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8248
8249private:
8250 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008252 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008253 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008255 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008256 location));
8257 }
8258};
8259
8260// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8261// should be ANR'd first.
8262TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008264 injectMotionEvent(*mDispatcher,
8265 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8266 AINPUT_SOURCE_TOUCHSCREEN)
8267 .pointer(PointerBuilder(0, ToolType::FINGER)
8268 .x(FOCUSED_WINDOW_LOCATION.x)
8269 .y(FOCUSED_WINDOW_LOCATION.y))
8270 .build()));
8271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8272 injectMotionEvent(*mDispatcher,
8273 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8274 AINPUT_SOURCE_TOUCHSCREEN)
8275 .pointer(PointerBuilder(0, ToolType::FINGER)
8276 .x(FOCUSED_WINDOW_LOCATION.x)
8277 .y(FOCUSED_WINDOW_LOCATION.y))
8278 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008279 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008280 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008281 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008282 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008283 // We consumed all events, so no ANR
8284 ASSERT_TRUE(mDispatcher->waitForIdle());
8285 mFakePolicy->assertNotifyAnrWasNotCalled();
8286
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008288 injectMotionEvent(*mDispatcher,
8289 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8290 AINPUT_SOURCE_TOUCHSCREEN)
8291 .pointer(PointerBuilder(0, ToolType::FINGER)
8292 .x(FOCUSED_WINDOW_LOCATION.x)
8293 .y(FOCUSED_WINDOW_LOCATION.y))
8294 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008295 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8296 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008297
8298 const std::chrono::duration timeout =
8299 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008300 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008301
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008302 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008303 mFocusedWindow->consumeMotionDown();
8304 // This cancel is generated because the connection was unresponsive
8305 mFocusedWindow->consumeMotionCancel();
8306 mFocusedWindow->assertNoEvents();
8307 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008308 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008309 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8310 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008311 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008312}
8313
8314// If we have 2 windows with identical timeouts that are both unresponsive,
8315// it doesn't matter which order they should have ANR.
8316// But we should receive ANR for both.
8317TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8318 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008319 mUnfocusedWindow->setDispatchingTimeout(
8320 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008321 mDispatcher->onWindowInfosChanged(
8322 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008323
8324 tapOnFocusedWindow();
8325 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008326 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008327 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8328 mFocusedWindow->getDispatchingTimeout(
8329 DISPATCHING_TIMEOUT)),
8330 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8331
8332 ASSERT_THAT(anrConnectionTokens,
8333 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8334 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008335
8336 ASSERT_TRUE(mDispatcher->waitForIdle());
8337 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008338
8339 mFocusedWindow->consumeMotionDown();
8340 mFocusedWindow->consumeMotionUp();
8341 mUnfocusedWindow->consumeMotionOutside();
8342
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008343 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8344 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008345
8346 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008347 ASSERT_THAT(responsiveTokens,
8348 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8349 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008350 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008351}
8352
8353// If a window is already not responding, the second tap on the same window should be ignored.
8354// We should also log an error to account for the dropped event (not tested here).
8355// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8356TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8357 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008358 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008359 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008360 // Receive the events, but don't respond
8361 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8362 ASSERT_TRUE(downEventSequenceNum);
8363 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8364 ASSERT_TRUE(upEventSequenceNum);
8365 const std::chrono::duration timeout =
8366 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008367 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008368
8369 // Tap once again
8370 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008371 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008372 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008373 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008374 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008375 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008376 FOCUSED_WINDOW_LOCATION));
8377 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8378 // valid touch target
8379 mUnfocusedWindow->assertNoEvents();
8380
8381 // Consume the first tap
8382 mFocusedWindow->finishEvent(*downEventSequenceNum);
8383 mFocusedWindow->finishEvent(*upEventSequenceNum);
8384 ASSERT_TRUE(mDispatcher->waitForIdle());
8385 // The second tap did not go to the focused window
8386 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008387 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008388 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8389 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008390 mFakePolicy->assertNotifyAnrWasNotCalled();
8391}
8392
8393// If you tap outside of all windows, there will not be ANR
8394TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008395 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008396 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008397 LOCATION_OUTSIDE_ALL_WINDOWS));
8398 ASSERT_TRUE(mDispatcher->waitForIdle());
8399 mFakePolicy->assertNotifyAnrWasNotCalled();
8400}
8401
8402// Since the focused window is paused, tapping on it should not produce any events
8403TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8404 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008405 mDispatcher->onWindowInfosChanged(
8406 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008407
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008409 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008410 FOCUSED_WINDOW_LOCATION));
8411
8412 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8413 ASSERT_TRUE(mDispatcher->waitForIdle());
8414 // Should not ANR because the window is paused, and touches shouldn't go to it
8415 mFakePolicy->assertNotifyAnrWasNotCalled();
8416
8417 mFocusedWindow->assertNoEvents();
8418 mUnfocusedWindow->assertNoEvents();
8419}
8420
8421/**
8422 * 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 -07008423 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008424 * If a different window becomes focused at this time, the key should go to that window instead.
8425 *
8426 * Warning!!!
8427 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8428 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008429 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008430 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8431 *
8432 * If that value changes, this test should also change.
8433 */
8434TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8435 // Set a long ANR timeout to prevent it from triggering
8436 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008437 mDispatcher->onWindowInfosChanged(
8438 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008439
8440 tapOnUnfocusedWindow();
8441 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8442 ASSERT_TRUE(downSequenceNum);
8443 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8444 ASSERT_TRUE(upSequenceNum);
8445 // Don't finish the events yet, and send a key
8446 // Injection will succeed because we will eventually give up and send the key to the focused
8447 // window even if motions are still being processed.
8448
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008449 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008450 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8451 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008453 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008454 // and the key remains pending, waiting for the touch events to be processed.
8455 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8456 // under the hood.
8457 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8458 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008459
8460 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008461 mFocusedWindow->setFocusable(false);
8462 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008463 mDispatcher->onWindowInfosChanged(
8464 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008465 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008466
8467 // Focus events should precede the key events
8468 mUnfocusedWindow->consumeFocusEvent(true);
8469 mFocusedWindow->consumeFocusEvent(false);
8470
8471 // Finish the tap events, which should unblock dispatcher
8472 mUnfocusedWindow->finishEvent(*downSequenceNum);
8473 mUnfocusedWindow->finishEvent(*upSequenceNum);
8474
8475 // Now that all queues are cleared and no backlog in the connections, the key event
8476 // can finally go to the newly focused "mUnfocusedWindow".
8477 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8478 mFocusedWindow->assertNoEvents();
8479 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008480 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008481}
8482
8483// When the touch stream is split across 2 windows, and one of them does not respond,
8484// then ANR should be raised and the touch should be canceled for the unresponsive window.
8485// The other window should not be affected by that.
8486TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8487 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008488 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8489 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8490 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008491 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008492 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008493
8494 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008495 mDispatcher->notifyMotion(
8496 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8497 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008498
8499 const std::chrono::duration timeout =
8500 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008501 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008502
8503 mUnfocusedWindow->consumeMotionDown();
8504 mFocusedWindow->consumeMotionDown();
8505 // Focused window may or may not receive ACTION_MOVE
8506 // But it should definitely receive ACTION_CANCEL due to the ANR
8507 InputEvent* event;
8508 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8509 ASSERT_TRUE(moveOrCancelSequenceNum);
8510 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8511 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008512 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008513 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8514 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8515 mFocusedWindow->consumeMotionCancel();
8516 } else {
8517 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8518 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008519 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008520 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8521 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008522
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008523 mUnfocusedWindow->assertNoEvents();
8524 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008525 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008526}
8527
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008528/**
8529 * If we have no focused window, and a key comes in, we start the ANR timer.
8530 * The focused application should add a focused window before the timer runs out to prevent ANR.
8531 *
8532 * If the user touches another application during this time, the key should be dropped.
8533 * Next, if a new focused window comes in, without toggling the focused application,
8534 * then no ANR should occur.
8535 *
8536 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8537 * but in some cases the policy may not update the focused application.
8538 */
8539TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8540 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8541 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008542 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008543 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8544 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8545 mFocusedWindow->setFocusable(false);
8546
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008547 mDispatcher->onWindowInfosChanged(
8548 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008549 mFocusedWindow->consumeFocusEvent(false);
8550
8551 // Send a key. The ANR timer should start because there is no focused window.
8552 // 'focusedApplication' will get blamed if this timer completes.
8553 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008554 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008555 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8556 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008557 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008559
8560 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8561 // then the injected touches won't cause the focused event to get dropped.
8562 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8563 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8564 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8565 // For this test, it means that the key would get delivered to the window once it becomes
8566 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008567 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008568
8569 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008570 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8571 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8572 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008573
8574 // We do not consume the motion right away, because that would require dispatcher to first
8575 // process (== drop) the key event, and by that time, ANR will be raised.
8576 // Set the focused window first.
8577 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008578 mDispatcher->onWindowInfosChanged(
8579 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008580 setFocusedWindow(mFocusedWindow);
8581 mFocusedWindow->consumeFocusEvent(true);
8582 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8583 // to another application. This could be a bug / behaviour in the policy.
8584
8585 mUnfocusedWindow->consumeMotionDown();
8586
8587 ASSERT_TRUE(mDispatcher->waitForIdle());
8588 // Should not ANR because we actually have a focused window. It was just added too slowly.
8589 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8590}
8591
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008592// These tests ensure we cannot send touch events to a window that's positioned behind a window
8593// that has feature NO_INPUT_CHANNEL.
8594// Layout:
8595// Top (closest to user)
8596// mNoInputWindow (above all windows)
8597// mBottomWindow
8598// Bottom (furthest from user)
8599class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8600 virtual void SetUp() override {
8601 InputDispatcherTest::SetUp();
8602
8603 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008604 mNoInputWindow =
8605 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8606 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008607 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008608 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008609 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8610 // It's perfectly valid for this window to not have an associated input channel
8611
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008612 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8613 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008614 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8615
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008616 mDispatcher->onWindowInfosChanged(
8617 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008618 }
8619
8620protected:
8621 std::shared_ptr<FakeApplicationHandle> mApplication;
8622 sp<FakeWindowHandle> mNoInputWindow;
8623 sp<FakeWindowHandle> mBottomWindow;
8624};
8625
8626TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8627 PointF touchedPoint = {10, 10};
8628
Prabir Pradhan678438e2023-04-13 19:32:51 +00008629 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8630 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8631 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008632
8633 mNoInputWindow->assertNoEvents();
8634 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8635 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8636 // and therefore should prevent mBottomWindow from receiving touches
8637 mBottomWindow->assertNoEvents();
8638}
8639
8640/**
8641 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8642 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8643 */
8644TEST_F(InputDispatcherMultiWindowOcclusionTests,
8645 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008646 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8647 "Window with input channel and NO_INPUT_CHANNEL",
8648 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008649
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008650 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008651 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008652 mDispatcher->onWindowInfosChanged(
8653 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008654
8655 PointF touchedPoint = {10, 10};
8656
Prabir Pradhan678438e2023-04-13 19:32:51 +00008657 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8658 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8659 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008660
8661 mNoInputWindow->assertNoEvents();
8662 mBottomWindow->assertNoEvents();
8663}
8664
Vishnu Nair958da932020-08-21 17:12:37 -07008665class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8666protected:
8667 std::shared_ptr<FakeApplicationHandle> mApp;
8668 sp<FakeWindowHandle> mWindow;
8669 sp<FakeWindowHandle> mMirror;
8670
8671 virtual void SetUp() override {
8672 InputDispatcherTest::SetUp();
8673 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008674 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8675 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8676 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008677 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8678 mWindow->setFocusable(true);
8679 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008680 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008681 }
8682};
8683
8684TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8685 // Request focus on a mirrored window
8686 setFocusedWindow(mMirror);
8687
8688 // window gets focused
8689 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008691 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008692 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8693}
8694
8695// A focused & mirrored window remains focused only if the window and its mirror are both
8696// focusable.
8697TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8698 setFocusedWindow(mMirror);
8699
8700 // window gets focused
8701 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008703 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008704 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008706 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008707 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8708
8709 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008710 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008711
8712 // window loses focus since one of the windows associated with the token in not focusable
8713 mWindow->consumeFocusEvent(false);
8714
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008715 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008716 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008717 mWindow->assertNoEvents();
8718}
8719
8720// A focused & mirrored window remains focused until the window and its mirror both become
8721// invisible.
8722TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8723 setFocusedWindow(mMirror);
8724
8725 // window gets focused
8726 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008728 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008729 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008731 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008732 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8733
8734 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008735 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008736
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008738 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008739 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008741 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008742 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8743
8744 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008745 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008746
8747 // window loses focus only after all windows associated with the token become invisible.
8748 mWindow->consumeFocusEvent(false);
8749
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008750 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008751 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008752 mWindow->assertNoEvents();
8753}
8754
8755// A focused & mirrored window remains focused until both windows are removed.
8756TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8757 setFocusedWindow(mMirror);
8758
8759 // window gets focused
8760 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008762 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008763 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008765 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008766 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8767
8768 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008769 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008770
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008772 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008773 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008775 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008776 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8777
8778 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008779 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008780 mWindow->consumeFocusEvent(false);
8781
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008782 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008783 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008784 mWindow->assertNoEvents();
8785}
8786
8787// Focus request can be pending until one window becomes visible.
8788TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8789 // Request focus on an invisible mirror.
8790 mWindow->setVisible(false);
8791 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008792 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008793 setFocusedWindow(mMirror);
8794
8795 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008797 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8798 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008799
8800 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008801 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008802
8803 // window gets focused
8804 mWindow->consumeFocusEvent(true);
8805 // window gets the pending key event
8806 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8807}
Prabir Pradhan99987712020-11-10 18:43:05 -08008808
8809class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8810protected:
8811 std::shared_ptr<FakeApplicationHandle> mApp;
8812 sp<FakeWindowHandle> mWindow;
8813 sp<FakeWindowHandle> mSecondWindow;
8814
8815 void SetUp() override {
8816 InputDispatcherTest::SetUp();
8817 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008818 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008819 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008820 mSecondWindow =
8821 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008822 mSecondWindow->setFocusable(true);
8823
8824 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008825 mDispatcher->onWindowInfosChanged(
8826 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008827
8828 setFocusedWindow(mWindow);
8829 mWindow->consumeFocusEvent(true);
8830 }
8831
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008832 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008833 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008834 }
8835
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008836 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8837 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008838 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008839 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8840 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008841 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008842 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008843 }
8844};
8845
8846TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8847 // Ensure that capture cannot be obtained for unfocused windows.
8848 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8849 mFakePolicy->assertSetPointerCaptureNotCalled();
8850 mSecondWindow->assertNoEvents();
8851
8852 // Ensure that capture can be enabled from the focus window.
8853 requestAndVerifyPointerCapture(mWindow, true);
8854
8855 // Ensure that capture cannot be disabled from a window that does not have capture.
8856 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8857 mFakePolicy->assertSetPointerCaptureNotCalled();
8858
8859 // Ensure that capture can be disabled from the window with capture.
8860 requestAndVerifyPointerCapture(mWindow, false);
8861}
8862
8863TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008864 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008865
8866 setFocusedWindow(mSecondWindow);
8867
8868 // Ensure that the capture disabled event was sent first.
8869 mWindow->consumeCaptureEvent(false);
8870 mWindow->consumeFocusEvent(false);
8871 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008872 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008873
8874 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008875 notifyPointerCaptureChanged({});
8876 notifyPointerCaptureChanged(request);
8877 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008878 mWindow->assertNoEvents();
8879 mSecondWindow->assertNoEvents();
8880 mFakePolicy->assertSetPointerCaptureNotCalled();
8881}
8882
8883TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008884 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008885
8886 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008887 notifyPointerCaptureChanged({});
8888 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008889
8890 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008891 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008892 mWindow->consumeCaptureEvent(false);
8893 mWindow->assertNoEvents();
8894}
8895
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008896TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8897 requestAndVerifyPointerCapture(mWindow, true);
8898
8899 // The first window loses focus.
8900 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008901 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008902 mWindow->consumeCaptureEvent(false);
8903
8904 // Request Pointer Capture from the second window before the notification from InputReader
8905 // arrives.
8906 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008907 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008908
8909 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008910 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008911
8912 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008913 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008914
8915 mSecondWindow->consumeFocusEvent(true);
8916 mSecondWindow->consumeCaptureEvent(true);
8917}
8918
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008919TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8920 // App repeatedly enables and disables capture.
8921 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8922 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8923 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8924 mFakePolicy->assertSetPointerCaptureCalled(false);
8925 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8926 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8927
8928 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8929 // first request is now stale, this should do nothing.
8930 notifyPointerCaptureChanged(firstRequest);
8931 mWindow->assertNoEvents();
8932
8933 // InputReader notifies that the second request was enabled.
8934 notifyPointerCaptureChanged(secondRequest);
8935 mWindow->consumeCaptureEvent(true);
8936}
8937
Prabir Pradhan7092e262022-05-03 16:51:09 +00008938TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8939 requestAndVerifyPointerCapture(mWindow, true);
8940
8941 // App toggles pointer capture off and on.
8942 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8943 mFakePolicy->assertSetPointerCaptureCalled(false);
8944
8945 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8946 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8947
8948 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8949 // preceding "disable" request.
8950 notifyPointerCaptureChanged(enableRequest);
8951
8952 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8953 // any notifications.
8954 mWindow->assertNoEvents();
8955}
8956
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008957/**
8958 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8959 * mouse movements don't affect the previous mouse hovering state.
8960 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8961 * HOVER_MOVE events).
8962 */
8963TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8964 // Mouse hover on the window
8965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8967 .build());
8968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8969 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8970 .build());
8971
8972 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8973 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8974
8975 // Start pointer capture
8976 requestAndVerifyPointerCapture(mWindow, true);
8977
8978 // Send some relative mouse movements and receive them in the window.
8979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8980 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8981 .build());
8982 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8983 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8984
8985 // Stop pointer capture
8986 requestAndVerifyPointerCapture(mWindow, false);
8987
8988 // Continue hovering on the window
8989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8990 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8991 .build());
8992 mWindow->consumeMotionEvent(
8993 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8994
8995 mWindow->assertNoEvents();
8996}
8997
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008998class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8999protected:
9000 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009001
9002 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9003 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9004
9005 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9006 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9007
9008 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9009 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9010 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9011 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9012 MAXIMUM_OBSCURING_OPACITY);
9013
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009014 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9015 static constexpr gui::Uid APP_B_UID{10002};
9016 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009017
9018 sp<FakeWindowHandle> mTouchWindow;
9019
9020 virtual void SetUp() override {
9021 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009022 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009023 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9024 }
9025
9026 virtual void TearDown() override {
9027 InputDispatcherTest::TearDown();
9028 mTouchWindow.clear();
9029 }
9030
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009031 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009032 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009033 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009034 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009035 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009036 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009037 return window;
9038 }
9039
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009040 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009041 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9042 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009043 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009044 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009045 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009046 return window;
9047 }
9048
9049 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9051 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9052 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009053 }
9054};
9055
9056TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009057 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009058 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009059 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009060
9061 touch();
9062
9063 mTouchWindow->assertNoEvents();
9064}
9065
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009066TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009067 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9068 const sp<FakeWindowHandle>& w =
9069 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009070 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009071
9072 touch();
9073
9074 mTouchWindow->assertNoEvents();
9075}
9076
9077TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009078 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9079 const sp<FakeWindowHandle>& w =
9080 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009081 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009082
9083 touch();
9084
9085 w->assertNoEvents();
9086}
9087
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009088TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009089 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009090 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009091
9092 touch();
9093
9094 mTouchWindow->consumeAnyMotionDown();
9095}
9096
9097TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009098 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009099 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009100 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009101 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009102
9103 touch({PointF{100, 100}});
9104
9105 mTouchWindow->consumeAnyMotionDown();
9106}
9107
9108TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009109 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009110 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009111 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009112
9113 touch();
9114
9115 mTouchWindow->consumeAnyMotionDown();
9116}
9117
9118TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9119 const sp<FakeWindowHandle>& w =
9120 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009121 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009122
9123 touch();
9124
9125 mTouchWindow->consumeAnyMotionDown();
9126}
9127
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009128TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9129 const sp<FakeWindowHandle>& w =
9130 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009131 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009132
9133 touch();
9134
9135 w->assertNoEvents();
9136}
9137
9138/**
9139 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9140 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9141 * window, the occluding window will still receive ACTION_OUTSIDE event.
9142 */
9143TEST_F(InputDispatcherUntrustedTouchesTest,
9144 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9145 const sp<FakeWindowHandle>& w =
9146 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009147 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009148 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009149
9150 touch();
9151
9152 w->consumeMotionOutside();
9153}
9154
9155TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9156 const sp<FakeWindowHandle>& w =
9157 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009158 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009159 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009160
9161 touch();
9162
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009163 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009164}
9165
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009166TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009167 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009168 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9169 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009170 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009171
9172 touch();
9173
9174 mTouchWindow->consumeAnyMotionDown();
9175}
9176
9177TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9178 const sp<FakeWindowHandle>& w =
9179 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9180 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009181 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009182
9183 touch();
9184
9185 mTouchWindow->consumeAnyMotionDown();
9186}
9187
9188TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009189 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009190 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9191 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009192 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009193
9194 touch();
9195
9196 mTouchWindow->assertNoEvents();
9197}
9198
9199TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9200 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9201 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009202 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9203 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009204 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009205 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9206 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009207 mDispatcher->onWindowInfosChanged(
9208 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009209
9210 touch();
9211
9212 mTouchWindow->assertNoEvents();
9213}
9214
9215TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9216 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9217 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009218 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9219 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009220 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009221 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9222 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009223 mDispatcher->onWindowInfosChanged(
9224 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009225
9226 touch();
9227
9228 mTouchWindow->consumeAnyMotionDown();
9229}
9230
9231TEST_F(InputDispatcherUntrustedTouchesTest,
9232 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9233 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009234 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9235 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009236 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009237 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9238 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009239 mDispatcher->onWindowInfosChanged(
9240 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009241
9242 touch();
9243
9244 mTouchWindow->consumeAnyMotionDown();
9245}
9246
9247TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9248 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009249 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9250 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009251 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009252 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9253 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009254 mDispatcher->onWindowInfosChanged(
9255 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009256
9257 touch();
9258
9259 mTouchWindow->assertNoEvents();
9260}
9261
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009262TEST_F(InputDispatcherUntrustedTouchesTest,
9263 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9264 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009265 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9266 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009267 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009268 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9269 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009270 mDispatcher->onWindowInfosChanged(
9271 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009272
9273 touch();
9274
9275 mTouchWindow->assertNoEvents();
9276}
9277
9278TEST_F(InputDispatcherUntrustedTouchesTest,
9279 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9280 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009281 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9282 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009283 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009284 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9285 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009286 mDispatcher->onWindowInfosChanged(
9287 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009288
9289 touch();
9290
9291 mTouchWindow->consumeAnyMotionDown();
9292}
9293
9294TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9295 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009296 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9297 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009298 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009299
9300 touch();
9301
9302 mTouchWindow->consumeAnyMotionDown();
9303}
9304
9305TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9306 const sp<FakeWindowHandle>& w =
9307 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009308 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009309
9310 touch();
9311
9312 mTouchWindow->consumeAnyMotionDown();
9313}
9314
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009315TEST_F(InputDispatcherUntrustedTouchesTest,
9316 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9317 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9318 const sp<FakeWindowHandle>& w =
9319 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009320 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009321
9322 touch();
9323
9324 mTouchWindow->assertNoEvents();
9325}
9326
9327TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9328 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9329 const sp<FakeWindowHandle>& w =
9330 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009331 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009332
9333 touch();
9334
9335 mTouchWindow->consumeAnyMotionDown();
9336}
9337
9338TEST_F(InputDispatcherUntrustedTouchesTest,
9339 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9340 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9341 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009342 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9343 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009344 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009345
9346 touch();
9347
9348 mTouchWindow->consumeAnyMotionDown();
9349}
9350
9351TEST_F(InputDispatcherUntrustedTouchesTest,
9352 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9353 const sp<FakeWindowHandle>& w1 =
9354 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9355 OPACITY_BELOW_THRESHOLD);
9356 const sp<FakeWindowHandle>& w2 =
9357 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9358 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009359 mDispatcher->onWindowInfosChanged(
9360 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009361
9362 touch();
9363
9364 mTouchWindow->assertNoEvents();
9365}
9366
9367/**
9368 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9369 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9370 * (which alone would result in allowing touches) does not affect the blocking behavior.
9371 */
9372TEST_F(InputDispatcherUntrustedTouchesTest,
9373 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9374 const sp<FakeWindowHandle>& wB =
9375 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9376 OPACITY_BELOW_THRESHOLD);
9377 const sp<FakeWindowHandle>& wC =
9378 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9379 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009380 mDispatcher->onWindowInfosChanged(
9381 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009382
9383 touch();
9384
9385 mTouchWindow->assertNoEvents();
9386}
9387
9388/**
9389 * This test is testing that a window from a different UID but with same application token doesn't
9390 * block the touch. Apps can share the application token for close UI collaboration for example.
9391 */
9392TEST_F(InputDispatcherUntrustedTouchesTest,
9393 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9394 const sp<FakeWindowHandle>& w =
9395 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9396 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009397 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009398
9399 touch();
9400
9401 mTouchWindow->consumeAnyMotionDown();
9402}
9403
arthurhungb89ccb02020-12-30 16:19:01 +08009404class InputDispatcherDragTests : public InputDispatcherTest {
9405protected:
9406 std::shared_ptr<FakeApplicationHandle> mApp;
9407 sp<FakeWindowHandle> mWindow;
9408 sp<FakeWindowHandle> mSecondWindow;
9409 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009410 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009411 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9412 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009413
9414 void SetUp() override {
9415 InputDispatcherTest::SetUp();
9416 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009417 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009418 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009419
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009420 mSecondWindow =
9421 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009422 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009423
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009424 mSpyWindow =
9425 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009426 mSpyWindow->setSpy(true);
9427 mSpyWindow->setTrustedOverlay(true);
9428 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9429
arthurhungb89ccb02020-12-30 16:19:01 +08009430 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009431 mDispatcher->onWindowInfosChanged(
9432 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9433 {},
9434 0,
9435 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009436 }
9437
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009438 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9439 switch (fromSource) {
9440 case AINPUT_SOURCE_TOUCHSCREEN:
9441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009443 ADISPLAY_ID_DEFAULT, {50, 50}))
9444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9445 break;
9446 case AINPUT_SOURCE_STYLUS:
9447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009448 injectMotionEvent(*mDispatcher,
9449 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9450 AINPUT_SOURCE_STYLUS)
9451 .buttonState(
9452 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9453 .pointer(PointerBuilder(0, ToolType::STYLUS)
9454 .x(50)
9455 .y(50))
9456 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009457 break;
9458 case AINPUT_SOURCE_MOUSE:
9459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009460 injectMotionEvent(*mDispatcher,
9461 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9462 AINPUT_SOURCE_MOUSE)
9463 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9464 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9465 ToolType::MOUSE)
9466 .x(50)
9467 .y(50))
9468 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009469 break;
9470 default:
9471 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9472 }
arthurhungb89ccb02020-12-30 16:19:01 +08009473
9474 // Window should receive motion event.
9475 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009476 // Spy window should also receive motion event
9477 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009478 }
9479
9480 // Start performing drag, we will create a drag window and transfer touch to it.
9481 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9482 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009483 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009484 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009485 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009486 }
arthurhungb89ccb02020-12-30 16:19:01 +08009487
9488 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009489 mDragWindow =
9490 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009491 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009492 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9493 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9494 {},
9495 0,
9496 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009497
9498 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009499 bool transferred =
9500 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009501 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009502 if (transferred) {
9503 mWindow->consumeMotionCancel();
9504 mDragWindow->consumeMotionDown();
9505 }
9506 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009507 }
9508};
9509
9510TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009511 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009512
9513 // Move on window.
9514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009515 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009516 ADISPLAY_ID_DEFAULT, {50, 50}))
9517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9518 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9519 mWindow->consumeDragEvent(false, 50, 50);
9520 mSecondWindow->assertNoEvents();
9521
9522 // Move to another window.
9523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009524 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009525 ADISPLAY_ID_DEFAULT, {150, 50}))
9526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9527 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9528 mWindow->consumeDragEvent(true, 150, 50);
9529 mSecondWindow->consumeDragEvent(false, 50, 50);
9530
9531 // Move back to original window.
9532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009533 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009534 ADISPLAY_ID_DEFAULT, {50, 50}))
9535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9536 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9537 mWindow->consumeDragEvent(false, 50, 50);
9538 mSecondWindow->consumeDragEvent(true, -50, 50);
9539
9540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009541 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9542 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9544 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9545 mWindow->assertNoEvents();
9546 mSecondWindow->assertNoEvents();
9547}
9548
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009549TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009550 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009551
9552 // No cancel event after drag start
9553 mSpyWindow->assertNoEvents();
9554
9555 const MotionEvent secondFingerDownEvent =
9556 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9557 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009558 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9559 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009560 .build();
9561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009562 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009563 InputEventInjectionSync::WAIT_FOR_RESULT))
9564 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9565
9566 // Receives cancel for first pointer after next pointer down
9567 mSpyWindow->consumeMotionCancel();
9568 mSpyWindow->consumeMotionDown();
9569
9570 mSpyWindow->assertNoEvents();
9571}
9572
arthurhungf452d0b2021-01-06 00:19:52 +08009573TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009574 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009575
9576 // Move on window.
9577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009578 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009579 ADISPLAY_ID_DEFAULT, {50, 50}))
9580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9581 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9582 mWindow->consumeDragEvent(false, 50, 50);
9583 mSecondWindow->assertNoEvents();
9584
9585 // Move to another window.
9586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009587 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009588 ADISPLAY_ID_DEFAULT, {150, 50}))
9589 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9590 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9591 mWindow->consumeDragEvent(true, 150, 50);
9592 mSecondWindow->consumeDragEvent(false, 50, 50);
9593
9594 // drop to another window.
9595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009596 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009597 {150, 50}))
9598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9599 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009600 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009601 mWindow->assertNoEvents();
9602 mSecondWindow->assertNoEvents();
9603}
9604
arthurhung6d4bed92021-03-17 11:59:33 +08009605TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009606 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009607
9608 // Move on window and keep button pressed.
9609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009610 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009611 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9612 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009613 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009614 .build()))
9615 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9616 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9617 mWindow->consumeDragEvent(false, 50, 50);
9618 mSecondWindow->assertNoEvents();
9619
9620 // Move to another window and release button, expect to drop item.
9621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009622 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009623 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9624 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009625 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009626 .build()))
9627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9628 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9629 mWindow->assertNoEvents();
9630 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009631 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009632
9633 // nothing to the window.
9634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009635 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009636 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9637 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009638 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009639 .build()))
9640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9641 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9642 mWindow->assertNoEvents();
9643 mSecondWindow->assertNoEvents();
9644}
9645
Arthur Hung54745652022-04-20 07:17:41 +00009646TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009647 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009648
9649 // Set second window invisible.
9650 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009651 mDispatcher->onWindowInfosChanged(
9652 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009653
9654 // Move on window.
9655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009656 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009657 ADISPLAY_ID_DEFAULT, {50, 50}))
9658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9659 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9660 mWindow->consumeDragEvent(false, 50, 50);
9661 mSecondWindow->assertNoEvents();
9662
9663 // Move to another window.
9664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009665 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009666 ADISPLAY_ID_DEFAULT, {150, 50}))
9667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9668 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9669 mWindow->consumeDragEvent(true, 150, 50);
9670 mSecondWindow->assertNoEvents();
9671
9672 // drop to another window.
9673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009674 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009675 {150, 50}))
9676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9677 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009678 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009679 mWindow->assertNoEvents();
9680 mSecondWindow->assertNoEvents();
9681}
9682
Arthur Hung54745652022-04-20 07:17:41 +00009683TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009684 // Ensure window could track pointerIds if it didn't support split touch.
9685 mWindow->setPreventSplitting(true);
9686
Arthur Hung54745652022-04-20 07:17:41 +00009687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009688 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009689 {50, 50}))
9690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9691 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9692
9693 const MotionEvent secondFingerDownEvent =
9694 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9695 .displayId(ADISPLAY_ID_DEFAULT)
9696 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009697 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9698 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009699 .build();
9700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009701 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009702 InputEventInjectionSync::WAIT_FOR_RESULT))
9703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009704 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009705
9706 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009707 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009708}
9709
9710TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9711 // First down on second window.
9712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009713 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009714 {150, 50}))
9715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9716
9717 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9718
9719 // Second down on first window.
9720 const MotionEvent secondFingerDownEvent =
9721 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9722 .displayId(ADISPLAY_ID_DEFAULT)
9723 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009724 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9725 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009726 .build();
9727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009728 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009729 InputEventInjectionSync::WAIT_FOR_RESULT))
9730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9731 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9732
9733 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009734 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009735
9736 // Move on window.
9737 const MotionEvent secondFingerMoveEvent =
9738 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9739 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009740 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9741 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009742 .build();
9743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009744 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009745 InputEventInjectionSync::WAIT_FOR_RESULT));
9746 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9747 mWindow->consumeDragEvent(false, 50, 50);
9748 mSecondWindow->consumeMotionMove();
9749
9750 // Release the drag pointer should perform drop.
9751 const MotionEvent secondFingerUpEvent =
9752 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9753 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009754 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9755 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009756 .build();
9757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009758 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009759 InputEventInjectionSync::WAIT_FOR_RESULT));
9760 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009761 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009762 mWindow->assertNoEvents();
9763 mSecondWindow->consumeMotionMove();
9764}
9765
Arthur Hung3915c1f2022-05-31 07:17:17 +00009766TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009767 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009768
9769 // Update window of second display.
9770 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009771 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009772 mDispatcher->onWindowInfosChanged(
9773 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9774 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9775 {},
9776 0,
9777 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009778
9779 // Let second display has a touch state.
9780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009781 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009782 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9783 AINPUT_SOURCE_TOUCHSCREEN)
9784 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009785 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009786 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009787 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009788 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009789 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009790 mDispatcher->onWindowInfosChanged(
9791 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9792 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9793 {},
9794 0,
9795 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009796
9797 // Move on window.
9798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009799 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009800 ADISPLAY_ID_DEFAULT, {50, 50}))
9801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9802 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9803 mWindow->consumeDragEvent(false, 50, 50);
9804 mSecondWindow->assertNoEvents();
9805
9806 // Move to another window.
9807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009808 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009809 ADISPLAY_ID_DEFAULT, {150, 50}))
9810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9811 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9812 mWindow->consumeDragEvent(true, 150, 50);
9813 mSecondWindow->consumeDragEvent(false, 50, 50);
9814
9815 // drop to another window.
9816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009817 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009818 {150, 50}))
9819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9820 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009821 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009822 mWindow->assertNoEvents();
9823 mSecondWindow->assertNoEvents();
9824}
9825
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009826TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9827 startDrag(true, AINPUT_SOURCE_MOUSE);
9828 // Move on window.
9829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009830 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009831 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9832 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009833 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009834 .x(50)
9835 .y(50))
9836 .build()))
9837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9838 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9839 mWindow->consumeDragEvent(false, 50, 50);
9840 mSecondWindow->assertNoEvents();
9841
9842 // Move to another window.
9843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009844 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009845 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9846 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009847 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009848 .x(150)
9849 .y(50))
9850 .build()))
9851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9852 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9853 mWindow->consumeDragEvent(true, 150, 50);
9854 mSecondWindow->consumeDragEvent(false, 50, 50);
9855
9856 // drop to another window.
9857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009858 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009859 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9860 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009861 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009862 .x(150)
9863 .y(50))
9864 .build()))
9865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9866 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009867 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009868 mWindow->assertNoEvents();
9869 mSecondWindow->assertNoEvents();
9870}
9871
Linnan Li5af92f92023-07-14 14:36:22 +08009872/**
9873 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9874 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9875 */
9876TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9877 // Down on second window
9878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9879 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9880 {150, 50}))
9881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9882
9883 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9884 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9885
9886 // Down on first window
9887 const MotionEvent secondFingerDownEvent =
9888 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9889 .displayId(ADISPLAY_ID_DEFAULT)
9890 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9891 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9892 .build();
9893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9894 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9895 InputEventInjectionSync::WAIT_FOR_RESULT))
9896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9897 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9898 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9899 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9900
9901 // Start drag on first window
9902 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9903
9904 // Trigger cancel
9905 mDispatcher->cancelCurrentTouch();
9906 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9907 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9908 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9909
9910 ASSERT_TRUE(mDispatcher->waitForIdle());
9911 // The D&D finished with nullptr
9912 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9913
9914 // Remove drag window
9915 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9916
9917 // Inject a simple gesture, ensure dispatcher not crashed
9918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9920 PointF{50, 50}))
9921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9922 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9923
9924 const MotionEvent moveEvent =
9925 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9926 .displayId(ADISPLAY_ID_DEFAULT)
9927 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9928 .build();
9929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9930 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9931 InputEventInjectionSync::WAIT_FOR_RESULT))
9932 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9933 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9934
9935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9936 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9937 {50, 50}))
9938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9939 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9940}
9941
Vishnu Nair062a8672021-09-03 16:07:44 -07009942class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9943
9944TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009946 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9947 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009948 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009949 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9950 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009951 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009952 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009953 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009954
9955 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009956 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009957 window->assertNoEvents();
9958
Prabir Pradhan678438e2023-04-13 19:32:51 +00009959 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9960 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009961 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9962 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009963 window->assertNoEvents();
9964
9965 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009966 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009968
Prabir Pradhan678438e2023-04-13 19:32:51 +00009969 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009970 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9971
Prabir Pradhan678438e2023-04-13 19:32:51 +00009972 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9973 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009974 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9975 window->assertNoEvents();
9976}
9977
9978TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9979 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9980 std::make_shared<FakeApplicationHandle>();
9981 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009982 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9983 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009984 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009985 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009986 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009988 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9989 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009990 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009991 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009992 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9993 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009994 mDispatcher->onWindowInfosChanged(
9995 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009996 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009997 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009998
9999 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010000 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010001 window->assertNoEvents();
10002
Prabir Pradhan678438e2023-04-13 19:32:51 +000010003 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10004 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010005 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10006 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010007 window->assertNoEvents();
10008
10009 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010010 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010011 mDispatcher->onWindowInfosChanged(
10012 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010013
Prabir Pradhan678438e2023-04-13 19:32:51 +000010014 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010015 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10016
Prabir Pradhan678438e2023-04-13 19:32:51 +000010017 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10018 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010019 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10020 window->assertNoEvents();
10021}
10022
10023TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10024 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10025 std::make_shared<FakeApplicationHandle>();
10026 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010027 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10028 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010029 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010030 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010031 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010033 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10034 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010035 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010036 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010037 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10038 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010039 mDispatcher->onWindowInfosChanged(
10040 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010041 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010042 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010043
10044 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010045 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010046 window->assertNoEvents();
10047
Prabir Pradhan678438e2023-04-13 19:32:51 +000010048 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10049 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10051 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010052 window->assertNoEvents();
10053
10054 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010055 mDispatcher->onWindowInfosChanged(
10056 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010057
Prabir Pradhan678438e2023-04-13 19:32:51 +000010058 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010059 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10060
Prabir Pradhan678438e2023-04-13 19:32:51 +000010061 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10062 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010063 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10064 window->assertNoEvents();
10065}
10066
Antonio Kantekf16f2832021-09-28 04:39:20 +000010067class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10068protected:
10069 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010070 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010071 sp<FakeWindowHandle> mWindow;
10072 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010073 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010074
10075 void SetUp() override {
10076 InputDispatcherTest::SetUp();
10077
10078 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010079 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010080 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010081 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010082 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010083 mSecondWindow =
10084 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010085 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010086 mThirdWindow =
10087 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10088 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10089 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010090
10091 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010092 mDispatcher->onWindowInfosChanged(
10093 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10094 {},
10095 0,
10096 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010097 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010098 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010099
Antonio Kantek15beb512022-06-13 22:35:41 +000010100 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010101 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010102 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010103 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10104 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010105 mThirdWindow->assertNoEvents();
10106 }
10107
10108 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10109 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010110 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010111 SECOND_DISPLAY_ID)) {
10112 mWindow->assertNoEvents();
10113 mSecondWindow->assertNoEvents();
10114 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010115 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010116 }
10117
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010118 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010119 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010120 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10121 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010122 mWindow->consumeTouchModeEvent(inTouchMode);
10123 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010124 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010125 }
10126};
10127
Antonio Kantek26defcf2022-02-08 01:12:27 +000010128TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010129 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010130 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10131 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010132 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010133}
10134
Antonio Kantek26defcf2022-02-08 01:12:27 +000010135TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10136 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010137 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010138 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010139 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010140 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010141 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010142 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010143 mWindow->assertNoEvents();
10144 mSecondWindow->assertNoEvents();
10145}
10146
10147TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10148 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010149 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010150 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010151 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010152 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010153 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010154}
10155
Antonio Kantekf16f2832021-09-28 04:39:20 +000010156TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010157 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010158 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10159 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010160 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010161 mWindow->assertNoEvents();
10162 mSecondWindow->assertNoEvents();
10163}
10164
Antonio Kantek15beb512022-06-13 22:35:41 +000010165TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10166 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10167 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10168 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010169 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010170 mWindow->assertNoEvents();
10171 mSecondWindow->assertNoEvents();
10172 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10173}
10174
Antonio Kantek48710e42022-03-24 14:19:30 -070010175TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10176 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10178 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010179 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10180 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10181
10182 // Then remove focus.
10183 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010184 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010185
10186 // Assert that caller can switch touch mode by owning one of the last interacted window.
10187 const WindowInfo& windowInfo = *mWindow->getInfo();
10188 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10189 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010190 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010191}
10192
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010193class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10194public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010195 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010196 std::shared_ptr<FakeApplicationHandle> application =
10197 std::make_shared<FakeApplicationHandle>();
10198 std::string name = "Fake Spy ";
10199 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010200 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10201 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010202 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010203 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010204 return spy;
10205 }
10206
10207 sp<FakeWindowHandle> createForeground() {
10208 std::shared_ptr<FakeApplicationHandle> application =
10209 std::make_shared<FakeApplicationHandle>();
10210 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010211 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10212 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010213 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010214 return window;
10215 }
10216
10217private:
10218 int mSpyCount{0};
10219};
10220
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010221using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010222/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010223 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10224 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010225TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010226 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010227 ScopedSilentDeath _silentDeath;
10228
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010229 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010230 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010231 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010232 ".* not a trusted overlay");
10233}
10234
10235/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010236 * Input injection into a display with a spy window but no foreground windows should succeed.
10237 */
10238TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010239 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010240 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010241
10242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10245 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10246}
10247
10248/**
10249 * Verify the order in which different input windows receive events. The touched foreground window
10250 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10251 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10252 * receive events before ones belows it.
10253 *
10254 * Here, we set up a scenario with four windows in the following Z order from the top:
10255 * spy1, spy2, window, spy3.
10256 * We then inject an event and verify that the foreground "window" receives it first, followed by
10257 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10258 * window.
10259 */
10260TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10261 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010262 auto spy1 = createSpy();
10263 auto spy2 = createSpy();
10264 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010265 mDispatcher->onWindowInfosChanged(
10266 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010267 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10268 const size_t numChannels = channels.size();
10269
Michael Wright8e9a8562022-02-09 13:44:29 +000010270 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010271 if (!epollFd.ok()) {
10272 FAIL() << "Failed to create epoll fd";
10273 }
10274
10275 for (size_t i = 0; i < numChannels; i++) {
10276 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10277 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10278 FAIL() << "Failed to add fd to epoll";
10279 }
10280 }
10281
10282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010283 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10285
10286 std::vector<size_t> eventOrder;
10287 std::vector<struct epoll_event> events(numChannels);
10288 for (;;) {
10289 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10290 (100ms).count());
10291 if (nFds < 0) {
10292 FAIL() << "Failed to call epoll_wait";
10293 }
10294 if (nFds == 0) {
10295 break; // epoll_wait timed out
10296 }
10297 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010298 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010299 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010300 channels[i]->consumeMotionDown();
10301 }
10302 }
10303
10304 // Verify the order in which the events were received.
10305 EXPECT_EQ(3u, eventOrder.size());
10306 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10307 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10308 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10309}
10310
10311/**
10312 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10313 */
10314TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10315 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010316 auto spy = createSpy();
10317 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010318 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010319
10320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010321 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10323 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10324 spy->assertNoEvents();
10325}
10326
10327/**
10328 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10329 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10330 * to the window.
10331 */
10332TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10333 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010334 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010335 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010336 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010337
10338 // Inject an event outside the spy window's touchable region.
10339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010340 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010341 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10342 window->consumeMotionDown();
10343 spy->assertNoEvents();
10344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010345 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10347 window->consumeMotionUp();
10348 spy->assertNoEvents();
10349
10350 // Inject an event inside the spy window's touchable region.
10351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010352 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010353 {5, 10}))
10354 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10355 window->consumeMotionDown();
10356 spy->consumeMotionDown();
10357}
10358
10359/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010360 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010361 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010362 */
10363TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10364 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010365 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010366 auto spy = createSpy();
10367 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010368 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010369 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010370 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010371
10372 // Inject an event outside the spy window's frame and touchable region.
10373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010374 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010375 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10377 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010378 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010379}
10380
10381/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010382 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10383 * pointers that are down within its bounds.
10384 */
10385TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10386 auto windowLeft = createForeground();
10387 windowLeft->setFrame({0, 0, 100, 200});
10388 auto windowRight = createForeground();
10389 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010390 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010391 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010392 mDispatcher->onWindowInfosChanged(
10393 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010394
10395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010396 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010397 {50, 50}))
10398 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10399 windowLeft->consumeMotionDown();
10400 spy->consumeMotionDown();
10401
10402 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010403 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010404 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010405 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10406 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010407 .build();
10408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010409 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010410 InputEventInjectionSync::WAIT_FOR_RESULT))
10411 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10412 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010413 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010414}
10415
10416/**
10417 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10418 * the spy should receive the second pointer with ACTION_DOWN.
10419 */
10420TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10421 auto window = createForeground();
10422 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010423 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010424 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010425 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010426
10427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010428 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010429 {50, 50}))
10430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10431 window->consumeMotionDown();
10432 spyRight->assertNoEvents();
10433
10434 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010435 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010436 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010437 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10438 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010439 .build();
10440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010441 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010442 InputEventInjectionSync::WAIT_FOR_RESULT))
10443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010444 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010445 spyRight->consumeMotionDown();
10446}
10447
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010448/**
10449 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10450 * windows should be allowed to control split touch.
10451 */
10452TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010453 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010454 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010455 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010456 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010457
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010458 auto window = createForeground();
10459 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010460
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010461 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010462
10463 // First finger down, no window touched.
10464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010465 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010466 {100, 200}))
10467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10468 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10469 window->assertNoEvents();
10470
10471 // Second finger down on window, the window should receive touch down.
10472 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010473 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010474 .displayId(ADISPLAY_ID_DEFAULT)
10475 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010476 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10477 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010478 .build();
10479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010480 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010481 InputEventInjectionSync::WAIT_FOR_RESULT))
10482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10483
10484 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010485 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010486}
10487
10488/**
10489 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10490 * do not receive key events.
10491 */
10492TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010493 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010494 spy->setFocusable(false);
10495
10496 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010497 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010498 setFocusedWindow(window);
10499 window->consumeFocusEvent(true);
10500
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010502 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10503 window->consumeKeyDown(ADISPLAY_ID_NONE);
10504
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010506 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10507 window->consumeKeyUp(ADISPLAY_ID_NONE);
10508
10509 spy->assertNoEvents();
10510}
10511
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010512using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10513
10514/**
10515 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10516 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10517 */
10518TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10519 auto window = createForeground();
10520 auto spy1 = createSpy();
10521 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010522 mDispatcher->onWindowInfosChanged(
10523 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010524
10525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010526 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010527 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10528 window->consumeMotionDown();
10529 spy1->consumeMotionDown();
10530 spy2->consumeMotionDown();
10531
10532 // Pilfer pointers from the second spy window.
10533 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10534 spy2->assertNoEvents();
10535 spy1->consumeMotionCancel();
10536 window->consumeMotionCancel();
10537
10538 // The rest of the gesture should only be sent to the second spy window.
10539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010540 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010541 ADISPLAY_ID_DEFAULT))
10542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10543 spy2->consumeMotionMove();
10544 spy1->assertNoEvents();
10545 window->assertNoEvents();
10546}
10547
10548/**
10549 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10550 * in the middle of the gesture.
10551 */
10552TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10553 auto window = createForeground();
10554 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010555 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010556
10557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010558 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010559 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10560 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10561 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10562
10563 window->releaseChannel();
10564
10565 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10566
10567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010568 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10570 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10571}
10572
10573/**
10574 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10575 * the spy, but not to any other windows.
10576 */
10577TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10578 auto spy = createSpy();
10579 auto window = createForeground();
10580
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010581 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010582
10583 // First finger down on the window and the spy.
10584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010585 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010586 {100, 200}))
10587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10588 spy->consumeMotionDown();
10589 window->consumeMotionDown();
10590
10591 // Spy window pilfers the pointers.
10592 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10593 window->consumeMotionCancel();
10594
10595 // Second finger down on the window and spy, but the window should not receive the pointer down.
10596 const MotionEvent secondFingerDownEvent =
10597 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10598 .displayId(ADISPLAY_ID_DEFAULT)
10599 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010600 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10601 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010602 .build();
10603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010604 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010605 InputEventInjectionSync::WAIT_FOR_RESULT))
10606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10607
Harry Cutts33476232023-01-30 19:57:29 +000010608 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010609
10610 // Third finger goes down outside all windows, so injection should fail.
10611 const MotionEvent thirdFingerDownEvent =
10612 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10613 .displayId(ADISPLAY_ID_DEFAULT)
10614 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010615 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10616 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10617 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010618 .build();
10619 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010620 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010621 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010622 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010623
10624 spy->assertNoEvents();
10625 window->assertNoEvents();
10626}
10627
10628/**
10629 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10630 */
10631TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10632 auto spy = createSpy();
10633 spy->setFrame(Rect(0, 0, 100, 100));
10634 auto window = createForeground();
10635 window->setFrame(Rect(0, 0, 200, 200));
10636
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010637 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010638
10639 // First finger down on the window only
10640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010641 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010642 {150, 150}))
10643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10644 window->consumeMotionDown();
10645
10646 // Second finger down on the spy and window
10647 const MotionEvent secondFingerDownEvent =
10648 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10649 .displayId(ADISPLAY_ID_DEFAULT)
10650 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010651 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10652 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010653 .build();
10654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010655 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010656 InputEventInjectionSync::WAIT_FOR_RESULT))
10657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10658 spy->consumeMotionDown();
10659 window->consumeMotionPointerDown(1);
10660
10661 // Third finger down on the spy and window
10662 const MotionEvent thirdFingerDownEvent =
10663 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10664 .displayId(ADISPLAY_ID_DEFAULT)
10665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010666 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10667 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10668 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010669 .build();
10670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010671 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010672 InputEventInjectionSync::WAIT_FOR_RESULT))
10673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10674 spy->consumeMotionPointerDown(1);
10675 window->consumeMotionPointerDown(2);
10676
10677 // Spy window pilfers the pointers.
10678 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010679 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10680 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010681
10682 spy->assertNoEvents();
10683 window->assertNoEvents();
10684}
10685
10686/**
10687 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10688 * other windows should be canceled. If this results in the cancellation of all pointers for some
10689 * window, then that window should receive ACTION_CANCEL.
10690 */
10691TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10692 auto spy = createSpy();
10693 spy->setFrame(Rect(0, 0, 100, 100));
10694 auto window = createForeground();
10695 window->setFrame(Rect(0, 0, 200, 200));
10696
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010697 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010698
10699 // First finger down on both spy and window
10700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010701 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010702 {10, 10}))
10703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10704 window->consumeMotionDown();
10705 spy->consumeMotionDown();
10706
10707 // Second finger down on the spy and window
10708 const MotionEvent secondFingerDownEvent =
10709 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10710 .displayId(ADISPLAY_ID_DEFAULT)
10711 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010712 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10713 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010714 .build();
10715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010716 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010717 InputEventInjectionSync::WAIT_FOR_RESULT))
10718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10719 spy->consumeMotionPointerDown(1);
10720 window->consumeMotionPointerDown(1);
10721
10722 // Spy window pilfers the pointers.
10723 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10724 window->consumeMotionCancel();
10725
10726 spy->assertNoEvents();
10727 window->assertNoEvents();
10728}
10729
10730/**
10731 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10732 * be sent to other windows
10733 */
10734TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10735 auto spy = createSpy();
10736 spy->setFrame(Rect(0, 0, 100, 100));
10737 auto window = createForeground();
10738 window->setFrame(Rect(0, 0, 200, 200));
10739
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010740 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010741
10742 // First finger down on both window and spy
10743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010744 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010745 {10, 10}))
10746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10747 window->consumeMotionDown();
10748 spy->consumeMotionDown();
10749
10750 // Spy window pilfers the pointers.
10751 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10752 window->consumeMotionCancel();
10753
10754 // Second finger down on the window only
10755 const MotionEvent secondFingerDownEvent =
10756 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10757 .displayId(ADISPLAY_ID_DEFAULT)
10758 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010759 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10760 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010761 .build();
10762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010763 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010764 InputEventInjectionSync::WAIT_FOR_RESULT))
10765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10766 window->consumeMotionDown();
10767 window->assertNoEvents();
10768
10769 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10770 spy->consumeMotionMove();
10771 spy->assertNoEvents();
10772}
10773
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010774/**
10775 * A window on the left and a window on the right. Also, a spy window that's above all of the
10776 * windows, and spanning both left and right windows.
10777 * Send simultaneous motion streams from two different devices, one to the left window, and another
10778 * to the right window.
10779 * Pilfer from spy window.
10780 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10781 */
10782TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10783 sp<FakeWindowHandle> spy = createSpy();
10784 spy->setFrame(Rect(0, 0, 200, 200));
10785 sp<FakeWindowHandle> leftWindow = createForeground();
10786 leftWindow->setFrame(Rect(0, 0, 100, 100));
10787
10788 sp<FakeWindowHandle> rightWindow = createForeground();
10789 rightWindow->setFrame(Rect(100, 0, 200, 100));
10790
10791 constexpr int32_t stylusDeviceId = 1;
10792 constexpr int32_t touchDeviceId = 2;
10793
10794 mDispatcher->onWindowInfosChanged(
10795 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10796
10797 // Stylus down on left window and spy
10798 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10799 .deviceId(stylusDeviceId)
10800 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10801 .build());
10802 leftWindow->consumeMotionEvent(
10803 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10804 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10805
10806 // Finger down on right window and spy - but spy already has stylus
10807 mDispatcher->notifyMotion(
10808 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10809 .deviceId(touchDeviceId)
10810 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10811 .build());
10812 rightWindow->consumeMotionEvent(
10813 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010814 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010815
10816 // Act: pilfer from spy. Spy is currently receiving touch events.
10817 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010818 leftWindow->consumeMotionEvent(
10819 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010820 rightWindow->consumeMotionEvent(
10821 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10822
10823 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10824 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10825 .deviceId(stylusDeviceId)
10826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10827 .build());
10828 mDispatcher->notifyMotion(
10829 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10830 .deviceId(touchDeviceId)
10831 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10832 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010833 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010834
10835 spy->assertNoEvents();
10836 leftWindow->assertNoEvents();
10837 rightWindow->assertNoEvents();
10838}
10839
Prabir Pradhand65552b2021-10-07 11:23:50 -070010840class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10841public:
10842 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10843 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10844 std::make_shared<FakeApplicationHandle>();
10845 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010846 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10847 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010848 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010849 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010850 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010851 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010852 overlay->setTrustedOverlay(true);
10853
10854 std::shared_ptr<FakeApplicationHandle> application =
10855 std::make_shared<FakeApplicationHandle>();
10856 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010857 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10858 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010859 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010860 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010861
10862 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010863 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010864 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010865 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010866 return {std::move(overlay), std::move(window)};
10867 }
10868
10869 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010870 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010871 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010872 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010873 }
10874
10875 void sendStylusEvent(int32_t action) {
10876 NotifyMotionArgs motionArgs =
10877 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10878 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010879 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010880 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010881 }
10882};
10883
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010884using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10885
10886TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010887 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010888 ScopedSilentDeath _silentDeath;
10889
Prabir Pradhand65552b2021-10-07 11:23:50 -070010890 auto [overlay, window] = setupStylusOverlayScenario();
10891 overlay->setTrustedOverlay(false);
10892 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010893 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10894 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010895 ".* not a trusted overlay");
10896}
10897
10898TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10899 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010900 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010901
10902 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10903 overlay->consumeMotionDown();
10904 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10905 overlay->consumeMotionUp();
10906
10907 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10908 window->consumeMotionDown();
10909 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10910 window->consumeMotionUp();
10911
10912 overlay->assertNoEvents();
10913 window->assertNoEvents();
10914}
10915
10916TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10917 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010918 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010919 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010920
10921 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10922 overlay->consumeMotionDown();
10923 window->consumeMotionDown();
10924 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10925 overlay->consumeMotionUp();
10926 window->consumeMotionUp();
10927
10928 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10929 window->consumeMotionDown();
10930 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10931 window->consumeMotionUp();
10932
10933 overlay->assertNoEvents();
10934 window->assertNoEvents();
10935}
10936
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010937/**
10938 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10939 * The scenario is as follows:
10940 * - The stylus interceptor overlay is configured as a spy window.
10941 * - The stylus interceptor spy receives the start of a new stylus gesture.
10942 * - It pilfers pointers and then configures itself to no longer be a spy.
10943 * - The stylus interceptor continues to receive the rest of the gesture.
10944 */
10945TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10946 auto [overlay, window] = setupStylusOverlayScenario();
10947 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010948 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010949
10950 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10951 overlay->consumeMotionDown();
10952 window->consumeMotionDown();
10953
10954 // The interceptor pilfers the pointers.
10955 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10956 window->consumeMotionCancel();
10957
10958 // The interceptor configures itself so that it is no longer a spy.
10959 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010960 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010961
10962 // It continues to receive the rest of the stylus gesture.
10963 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10964 overlay->consumeMotionMove();
10965 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10966 overlay->consumeMotionUp();
10967
10968 window->assertNoEvents();
10969}
10970
Prabir Pradhan5735a322022-04-11 17:23:34 +000010971struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010972 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010973 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010974 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10975 std::unique_ptr<InputDispatcher>& mDispatcher;
10976
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010977 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010978 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10979
10980 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010981 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010982 ADISPLAY_ID_DEFAULT, {100, 200},
10983 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10984 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10985 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10986 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10987 }
10988
10989 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010990 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010991 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010992 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010993 mPolicyFlags);
10994 }
10995
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010996 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010997 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10998 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010999 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11000 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011001 window->setOwnerInfo(mPid, mUid);
11002 return window;
11003 }
11004};
11005
11006using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11007
11008TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011009 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011010 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011011 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011012
11013 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11014 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11015 window->consumeMotionDown();
11016
11017 setFocusedWindow(window);
11018 window->consumeFocusEvent(true);
11019
11020 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11021 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11022 window->consumeKeyDown(ADISPLAY_ID_NONE);
11023}
11024
11025TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011026 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011027 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011028 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011029
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011030 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011031 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11032 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11033
11034 setFocusedWindow(window);
11035 window->consumeFocusEvent(true);
11036
11037 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11038 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11039 window->assertNoEvents();
11040}
11041
11042TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011043 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011044 auto window = owner.createWindow("Owned window");
11045 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011046 spy->setSpy(true);
11047 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011048 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011049
11050 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11051 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11052 spy->consumeMotionDown();
11053 window->consumeMotionDown();
11054}
11055
11056TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011057 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011058 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011059
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011060 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011061 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011062 randosSpy->setSpy(true);
11063 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011064 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011065
11066 // The event is targeted at owner's window, so injection should succeed, but the spy should
11067 // not receive the event.
11068 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11069 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11070 randosSpy->assertNoEvents();
11071 window->consumeMotionDown();
11072}
11073
11074TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011075 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011076 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011077
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011078 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011079 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011080 randosSpy->setSpy(true);
11081 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011082 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011083
11084 // A user that has injection permission can inject into any window.
11085 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011086 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011087 ADISPLAY_ID_DEFAULT));
11088 randosSpy->consumeMotionDown();
11089 window->consumeMotionDown();
11090
11091 setFocusedWindow(randosSpy);
11092 randosSpy->consumeFocusEvent(true);
11093
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011094 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011095 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11096 window->assertNoEvents();
11097}
11098
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011099TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011100 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011101 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011102
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011103 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011104 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011105 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11106 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011107 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011108
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011109 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011110 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11111 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11112 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011113 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011114}
11115
Garfield Tane84e6f92019-08-29 17:28:41 -070011116} // namespace android::inputdispatcher