blob: d2ff097d18559697406f478af4151ddc103f1390 [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"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070019#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080020#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080021#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070022#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070023#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000024#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080025#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080026#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100027#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080029#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080032#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070033#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080034#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080035#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050038using android::gui::FocusRequest;
39using android::gui::TouchOcclusionMode;
40using android::gui::WindowInfo;
41using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080042using android::os::InputEventInjectionResult;
43using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080044
Garfield Tane84e6f92019-08-29 17:28:41 -070045namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080046
Dominik Laskowski2f01d772022-03-23 16:01:29 -070047using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080048using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049
Michael Wrightd02c5b62014-02-10 15:10:22 -080050// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000051static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
53// An arbitrary device id.
Prabir Pradhan5735a322022-04-11 17:23:34 +000054static constexpr int32_t DEVICE_ID = 1;
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
Jeff Brownf086ddb2014-02-11 14:28:48 -080056// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000057static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
58static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080059
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080060static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080061static constexpr int32_t POINTER_1_DOWN =
62 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000063static constexpr int32_t POINTER_2_DOWN =
64 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000065static constexpr int32_t POINTER_3_DOWN =
66 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080067static constexpr int32_t POINTER_1_UP =
68 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
69
Antonio Kantek15beb512022-06-13 22:35:41 +000070// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000071static constexpr int32_t WINDOW_PID = 999;
72static constexpr int32_t WINDOW_UID = 1001;
73
Antonio Kantek15beb512022-06-13 22:35:41 +000074// The default pid and uid for the windows created on the secondary display by the test.
75static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
76static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
77
Prabir Pradhan5735a322022-04-11 17:23:34 +000078// The default policy flags to use for event injection by tests.
79static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -080080
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000081// An arbitrary pid of the gesture monitor window
82static constexpr int32_t MONITOR_PID = 2001;
83
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080084static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
85
chaviwd1c23182019-12-20 18:44:56 -080086struct PointF {
87 float x;
88 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080089 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -080090};
Michael Wrightd02c5b62014-02-10 15:10:22 -080091
Gang Wang342c9272020-01-13 13:15:04 -050092/**
93 * Return a DOWN key event with KEYCODE_A.
94 */
95static KeyEvent getTestKeyEvent() {
96 KeyEvent event;
97
Garfield Tanfbe732e2020-01-24 11:26:14 -080098 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
99 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
100 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500101 return event;
102}
103
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000104static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
105 ASSERT_EQ(expectedAction, receivedAction)
106 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
107 << MotionEvent::actionToString(receivedAction);
108}
109
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800110MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
111 bool matches = action == arg.getAction();
112 if (!matches) {
113 *result_listener << "expected action " << MotionEvent::actionToString(action)
114 << ", but got " << MotionEvent::actionToString(arg.getAction());
115 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800116 if (action == AMOTION_EVENT_ACTION_DOWN) {
117 if (!matches) {
118 *result_listener << "; ";
119 }
120 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
121 matches &= arg.getDownTime() == arg.getEventTime();
122 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800123 if (action == AMOTION_EVENT_ACTION_CANCEL) {
124 if (!matches) {
125 *result_listener << "; ";
126 }
127 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
128 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
129 }
130 return matches;
131}
132
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800133MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
134 return arg.getDownTime() == downTime;
135}
136
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800137MATCHER_P(WithSource, source, "InputEvent with specified source") {
138 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
139 << inputEventSourceToString(arg.getSource());
140 return arg.getSource() == source;
141}
142
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800143MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
144 if (arg.getPointerCount() != 1) {
145 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
146 return false;
147 }
148 return arg.getX(0 /*pointerIndex*/) == x && arg.getY(0 /*pointerIndex*/) == y;
149}
150
151MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
152 // Build a map for the received pointers, by pointer id
153 std::map<int32_t /*pointerId*/, PointF> actualPointers;
154 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
155 const int32_t pointerId = arg.getPointerId(pointerIndex);
156 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
157 }
158 return pointers == actualPointers;
159}
160
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161// --- FakeInputDispatcherPolicy ---
162
163class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
164 InputDispatcherConfiguration mConfig;
165
Prabir Pradhanedd96402022-02-15 01:46:16 -0800166 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
167
Michael Wrightd02c5b62014-02-10 15:10:22 -0800168protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000169 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800170
171public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000172 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800173
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800174 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
176 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
177 EXPECT_EQ(event.getDisplayId(), args.displayId);
178
179 const auto& keyEvent = static_cast<const KeyEvent&>(event);
180 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
181 EXPECT_EQ(keyEvent.getAction(), args.action);
182 });
Jackal Guof9696682018-10-05 12:23:23 +0800183 }
184
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700185 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
186 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
187 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
188 EXPECT_EQ(event.getDisplayId(), args.displayId);
189
190 const auto& motionEvent = static_cast<const MotionEvent&>(event);
191 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
192 EXPECT_EQ(motionEvent.getAction(), args.action);
193 EXPECT_EQ(motionEvent.getX(0), point.x);
194 EXPECT_EQ(motionEvent.getY(0), point.y);
195 EXPECT_EQ(motionEvent.getRawX(0), point.x);
196 EXPECT_EQ(motionEvent.getRawY(0), point.y);
197 });
Jackal Guof9696682018-10-05 12:23:23 +0800198 }
199
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700200 void assertFilterInputEventWasNotCalled() {
201 std::scoped_lock lock(mLock);
202 ASSERT_EQ(nullptr, mFilteredEvent);
203 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700206 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 ASSERT_TRUE(mConfigurationChangedTime)
208 << "Timed out waiting for configuration changed call";
209 ASSERT_EQ(*mConfigurationChangedTime, when);
210 mConfigurationChangedTime = std::nullopt;
211 }
212
213 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700214 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800215 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800216 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800217 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
218 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
219 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
220 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
221 mLastNotifySwitch = std::nullopt;
222 }
223
chaviwfd6d3512019-03-25 13:23:49 -0700224 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700225 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800226 ASSERT_EQ(touchedToken, mOnPointerDownToken);
227 mOnPointerDownToken.clear();
228 }
229
230 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700231 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800232 ASSERT_TRUE(mOnPointerDownToken == nullptr)
233 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700234 }
235
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700236 // This function must be called soon after the expected ANR timer starts,
237 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500238 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700239 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500240 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800241 std::unique_lock lock(mLock);
242 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500243 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800244 ASSERT_NO_FATAL_FAILURE(
245 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500246 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700247 }
248
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000249 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800250 const sp<WindowInfoHandle>& window) {
251 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
252 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
253 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500254 }
255
Prabir Pradhanedd96402022-02-15 01:46:16 -0800256 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
257 const sp<IBinder>& expectedToken,
258 int32_t expectedPid) {
259 std::unique_lock lock(mLock);
260 android::base::ScopedLockAssertion assumeLocked(mLock);
261 AnrResult result;
262 ASSERT_NO_FATAL_FAILURE(result =
263 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
264 const auto& [token, pid] = result;
265 ASSERT_EQ(expectedToken, token);
266 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500267 }
268
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000270 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500271 std::unique_lock lock(mLock);
272 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800273 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
274 const auto& [token, _] = result;
275 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000276 }
277
Prabir Pradhanedd96402022-02-15 01:46:16 -0800278 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
279 int32_t expectedPid) {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
282 AnrResult result;
283 ASSERT_NO_FATAL_FAILURE(
284 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
285 const auto& [token, pid] = result;
286 ASSERT_EQ(expectedToken, token);
287 ASSERT_EQ(expectedPid, pid);
288 }
289
290 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000291 sp<IBinder> getResponsiveWindowToken() {
292 std::unique_lock lock(mLock);
293 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800294 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
295 const auto& [token, _] = result;
296 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700297 }
298
299 void assertNotifyAnrWasNotCalled() {
300 std::scoped_lock lock(mLock);
301 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800302 ASSERT_TRUE(mAnrWindows.empty());
303 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500304 << "ANR was not called, but please also consume the 'connection is responsive' "
305 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700306 }
307
Garfield Tan1c7bc862020-01-28 13:24:04 -0800308 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
309 mConfig.keyRepeatTimeout = timeout;
310 mConfig.keyRepeatDelay = delay;
311 }
312
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000313 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800314 std::unique_lock lock(mLock);
315 base::ScopedLockAssertion assumeLocked(mLock);
316
317 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
318 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 enabled;
321 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000322 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
323 << ") to be called.";
324 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800325 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000326 auto request = *mPointerCaptureRequest;
327 mPointerCaptureRequest.reset();
328 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800329 }
330
331 void assertSetPointerCaptureNotCalled() {
332 std::unique_lock lock(mLock);
333 base::ScopedLockAssertion assumeLocked(mLock);
334
335 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000336 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800337 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000338 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800339 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000340 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800341 }
342
arthurhungf452d0b2021-01-06 00:19:52 +0800343 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
344 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800345 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800346 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800347 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800348 }
349
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800350 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
351 std::unique_lock lock(mLock);
352 base::ScopedLockAssertion assumeLocked(mLock);
353 std::optional<sp<IBinder>> receivedToken =
354 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
355 mNotifyInputChannelBroken);
356 ASSERT_TRUE(receivedToken.has_value());
357 ASSERT_EQ(token, *receivedToken);
358 }
359
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800360 /**
361 * Set policy timeout. A value of zero means next key will not be intercepted.
362 */
363 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
364 mInterceptKeyTimeout = timeout;
365 }
366
Michael Wrightd02c5b62014-02-10 15:10:22 -0800367private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700368 std::mutex mLock;
369 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
370 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
371 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
372 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800373
Prabir Pradhan99987712020-11-10 18:43:05 -0800374 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000375
376 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800377
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700378 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700379 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800380 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
381 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700382 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800383 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
384 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700385
arthurhungf452d0b2021-01-06 00:19:52 +0800386 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800387 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800388
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800389 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
390
Prabir Pradhanedd96402022-02-15 01:46:16 -0800391 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
392 // for a specific container to become non-empty. When the container is non-empty, return the
393 // first entry from the container and erase it.
394 template <class T>
395 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
396 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
397 // If there is an ANR, Dispatcher won't be idle because there are still events
398 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
399 // before checking if ANR was called.
400 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
401 // to provide it some time to act. 100ms seems reasonable.
402 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
403 const std::chrono::time_point start = std::chrono::steady_clock::now();
404 std::optional<T> token =
405 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
406 if (!token.has_value()) {
407 ADD_FAILURE() << "Did not receive the ANR callback";
408 return {};
409 }
410
411 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
412 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
413 // the dispatcher started counting before this function was called
414 if (std::chrono::abs(timeout - waited) > 100ms) {
415 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
416 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
417 << "ms, but waited "
418 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
419 << "ms instead";
420 }
421 return *token;
422 }
423
424 template <class T>
425 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
426 std::queue<T>& storage,
427 std::unique_lock<std::mutex>& lock,
428 std::condition_variable& condition)
429 REQUIRES(mLock) {
430 condition.wait_for(lock, timeout,
431 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
432 if (storage.empty()) {
433 ADD_FAILURE() << "Did not receive the expected callback";
434 return std::nullopt;
435 }
436 T item = storage.front();
437 storage.pop();
438 return std::make_optional(item);
439 }
440
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600441 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700442 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800443 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800444 }
445
Prabir Pradhanedd96402022-02-15 01:46:16 -0800446 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
447 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700448 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800449 ASSERT_TRUE(pid.has_value());
450 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700451 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500452 }
453
Prabir Pradhanedd96402022-02-15 01:46:16 -0800454 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
455 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500456 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800457 ASSERT_TRUE(pid.has_value());
458 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500459 mNotifyAnr.notify_all();
460 }
461
462 void notifyNoFocusedWindowAnr(
463 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
464 std::scoped_lock lock(mLock);
465 mAnrApplications.push(applicationHandle);
466 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800467 }
468
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800469 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
470 std::scoped_lock lock(mLock);
471 mBrokenInputChannels.push(connectionToken);
472 mNotifyInputChannelBroken.notify_all();
473 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800474
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600475 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700476
Chris Yef59a2f42020-10-16 12:55:26 -0700477 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
478 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
479 const std::vector<float>& values) override {}
480
481 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
482 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000483
Chris Yefb552902021-02-03 17:18:37 -0800484 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
485
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600486 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800487 *outConfig = mConfig;
488 }
489
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600490 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700491 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800492 switch (inputEvent->getType()) {
493 case AINPUT_EVENT_TYPE_KEY: {
494 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800495 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800496 break;
497 }
498
499 case AINPUT_EVENT_TYPE_MOTION: {
500 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800501 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800502 break;
503 }
504 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 return true;
506 }
507
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800508 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
509 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
510 // Clear intercept state when we handled the event.
511 mInterceptKeyTimeout = 0ms;
512 }
513 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800514
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600515 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600517 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800518 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
519 // Clear intercept state so we could dispatch the event in next wake.
520 mInterceptKeyTimeout = 0ms;
521 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800522 }
523
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600524 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525 return false;
526 }
527
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600528 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
529 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700530 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800531 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
532 * essentially a passthrough for notifySwitch.
533 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800534 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800535 }
536
Sean Stoutb4e0a592021-02-23 07:34:53 -0800537 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800538
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600539 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700540 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700541 mOnPointerDownToken = newToken;
542 }
543
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000544 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800545 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000546 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800547 mPointerCaptureChangedCondition.notify_all();
548 }
549
arthurhungf452d0b2021-01-06 00:19:52 +0800550 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
551 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800552 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800553 mDropTargetWindowToken = token;
554 }
555
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700556 void assertFilterInputEventWasCalledInternal(
557 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700558 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800559 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700560 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800561 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800562 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563};
564
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565// --- InputDispatcherTest ---
566
567class InputDispatcherTest : public testing::Test {
568protected:
569 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700570 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800571
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000572 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700573 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800574 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800575 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000576 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700577 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800578 }
579
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000580 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700581 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700583 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800584 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700585
586 /**
587 * Used for debugging when writing the test
588 */
589 void dumpDispatcherState() {
590 std::string dump;
591 mDispatcher->dump(dump);
592 std::stringstream ss(dump);
593 std::string to;
594
595 while (std::getline(ss, to, '\n')) {
596 ALOGE("%s", to.c_str());
597 }
598 }
Vishnu Nair958da932020-08-21 17:12:37 -0700599
chaviw3277faf2021-05-19 16:45:23 -0500600 void setFocusedWindow(const sp<WindowInfoHandle>& window,
601 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700602 FocusRequest request;
603 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000604 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700605 if (focusedWindow) {
606 request.focusedToken = focusedWindow->getToken();
607 }
608 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
609 request.displayId = window->getInfo()->displayId;
610 mDispatcher->setFocusedWindow(request);
611 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800612};
613
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
615 KeyEvent event;
616
617 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800618 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
619 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600620 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
621 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800622 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000623 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
624 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625 << "Should reject key events with undefined action.";
626
627 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800628 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
629 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600630 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800631 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000632 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
633 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 << "Should reject key events with ACTION_MULTIPLE.";
635}
636
637TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
638 MotionEvent event;
639 PointerProperties pointerProperties[MAX_POINTERS + 1];
640 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800641 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800642 pointerProperties[i].clear();
643 pointerProperties[i].id = i;
644 pointerCoords[i].clear();
645 }
646
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800647 // Some constants commonly used below
648 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
649 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
650 constexpr int32_t metaState = AMETA_NONE;
651 constexpr MotionClassification classification = MotionClassification::NONE;
652
chaviw9eaa22c2020-07-01 16:21:27 -0700653 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800654 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800655 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700656 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
657 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700658 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
659 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700660 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800661 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000662 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
663 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664 << "Should reject motion events with undefined action.";
665
666 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800667 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800668 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
669 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
670 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
671 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500672 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800673 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000674 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
675 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676 << "Should reject motion events with pointer down index too large.";
677
Garfield Tanfbe732e2020-01-24 11:26:14 -0800678 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700679 AMOTION_EVENT_ACTION_POINTER_DOWN |
680 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700681 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
682 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700683 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500684 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800685 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000686 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
687 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800688 << "Should reject motion events with pointer down index too small.";
689
690 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800691 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800692 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
693 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
694 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
695 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500696 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800697 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
699 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800700 << "Should reject motion events with pointer up index too large.";
701
Garfield Tanfbe732e2020-01-24 11:26:14 -0800702 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700703 AMOTION_EVENT_ACTION_POINTER_UP |
704 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700705 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
706 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700707 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500708 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800709 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000710 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
711 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800712 << "Should reject motion events with pointer up index too small.";
713
714 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800715 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
716 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700717 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700718 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
719 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700720 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800721 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000722 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
723 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800724 << "Should reject motion events with 0 pointers.";
725
Garfield Tanfbe732e2020-01-24 11:26:14 -0800726 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
727 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700728 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700729 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
730 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000733 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject motion events with more than MAX_POINTERS pointers.";
736
737 // Rejects motion events with invalid pointer ids.
738 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800739 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
740 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700741 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700742 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
743 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700744 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800745 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000746 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
747 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800748 << "Should reject motion events with pointer ids less than 0.";
749
750 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800751 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
752 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700753 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700754 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
755 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700756 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800757 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000758 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
759 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800760 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
761
762 // Rejects motion events with duplicate pointer ids.
763 pointerProperties[0].id = 1;
764 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800765 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
766 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700767 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700768 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
769 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700770 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800771 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000772 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
773 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800774 << "Should reject motion events with duplicate pointer ids.";
775}
776
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800777/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
778
779TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
780 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800781 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800782 mDispatcher->notifyConfigurationChanged(&args);
783 ASSERT_TRUE(mDispatcher->waitForIdle());
784
785 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
786}
787
788TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800789 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
790 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800791 mDispatcher->notifySwitch(&args);
792
793 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
794 args.policyFlags |= POLICY_FLAG_TRUSTED;
795 mFakePolicy->assertNotifySwitchWasCalled(args);
796}
797
Arthur Hungb92218b2018-08-14 12:00:21 +0800798// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700799static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700800// Default input dispatching timeout if there is no focused application or paused window
801// from which to determine an appropriate dispatching timeout.
802static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
803 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
804 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800805
806class FakeApplicationHandle : public InputApplicationHandle {
807public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700808 FakeApplicationHandle() {
809 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700810 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500811 mInfo.dispatchingTimeoutMillis =
812 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700813 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800814 virtual ~FakeApplicationHandle() {}
815
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000816 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700817
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500818 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
819 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700820 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800821};
822
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800823class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800824public:
Garfield Tan15601662020-09-22 15:32:38 -0700825 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800826 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700827 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800828 }
829
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800830 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700831 InputEvent* event;
832 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
833 if (!consumeSeq) {
834 return nullptr;
835 }
836 finishEvent(*consumeSeq);
837 return event;
838 }
839
840 /**
841 * Receive an event without acknowledging it.
842 * Return the sequence number that could later be used to send finished signal.
843 */
844 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800845 uint32_t consumeSeq;
846 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800847
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800848 std::chrono::time_point start = std::chrono::steady_clock::now();
849 status_t status = WOULD_BLOCK;
850 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800851 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800852 &event);
853 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
854 if (elapsed > 100ms) {
855 break;
856 }
857 }
858
859 if (status == WOULD_BLOCK) {
860 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700861 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800862 }
863
864 if (status != OK) {
865 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700866 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800867 }
868 if (event == nullptr) {
869 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700870 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800871 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700872 if (outEvent != nullptr) {
873 *outEvent = event;
874 }
875 return consumeSeq;
876 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800877
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700878 /**
879 * To be used together with "receiveEvent" to complete the consumption of an event.
880 */
881 void finishEvent(uint32_t consumeSeq) {
882 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
883 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800884 }
885
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000886 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
887 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
888 ASSERT_EQ(OK, status);
889 }
890
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000891 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
892 std::optional<int32_t> expectedDisplayId,
893 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800894 InputEvent* event = consume();
895
896 ASSERT_NE(nullptr, event) << mName.c_str()
897 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800898 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700899 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800900 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800901
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000902 if (expectedDisplayId.has_value()) {
903 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
904 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800905
Tiger Huang8664f8c2018-10-11 19:14:35 +0800906 switch (expectedEventType) {
907 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800908 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
909 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000910 if (expectedFlags.has_value()) {
911 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
912 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800913 break;
914 }
915 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800916 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000917 assertMotionAction(expectedAction, motionEvent.getAction());
918
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000919 if (expectedFlags.has_value()) {
920 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
921 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800922 break;
923 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100924 case AINPUT_EVENT_TYPE_FOCUS: {
925 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
926 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800927 case AINPUT_EVENT_TYPE_CAPTURE: {
928 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
929 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000930 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
931 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
932 }
arthurhungb89ccb02020-12-30 16:19:01 +0800933 case AINPUT_EVENT_TYPE_DRAG: {
934 FAIL() << "Use 'consumeDragEvent' for DRAG events";
935 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800936 default: {
937 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
938 }
939 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800940 }
941
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100942 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
943 InputEvent* event = consume();
944 ASSERT_NE(nullptr, event) << mName.c_str()
945 << ": consumer should have returned non-NULL event.";
946 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
947 << "Got " << inputEventTypeToString(event->getType())
948 << " event instead of FOCUS event";
949
950 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
951 << mName.c_str() << ": event displayId should always be NONE.";
952
953 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
954 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100955 }
956
Prabir Pradhan99987712020-11-10 18:43:05 -0800957 void consumeCaptureEvent(bool hasCapture) {
958 const InputEvent* event = consume();
959 ASSERT_NE(nullptr, event) << mName.c_str()
960 << ": consumer should have returned non-NULL event.";
961 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
962 << "Got " << inputEventTypeToString(event->getType())
963 << " event instead of CAPTURE event";
964
965 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
966 << mName.c_str() << ": event displayId should always be NONE.";
967
968 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
969 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
970 }
971
arthurhungb89ccb02020-12-30 16:19:01 +0800972 void consumeDragEvent(bool isExiting, float x, float y) {
973 const InputEvent* event = consume();
974 ASSERT_NE(nullptr, event) << mName.c_str()
975 << ": consumer should have returned non-NULL event.";
976 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
977 << "Got " << inputEventTypeToString(event->getType())
978 << " event instead of DRAG event";
979
980 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
981 << mName.c_str() << ": event displayId should always be NONE.";
982
983 const auto& dragEvent = static_cast<const DragEvent&>(*event);
984 EXPECT_EQ(isExiting, dragEvent.isExiting());
985 EXPECT_EQ(x, dragEvent.getX());
986 EXPECT_EQ(y, dragEvent.getY());
987 }
988
Antonio Kantekf16f2832021-09-28 04:39:20 +0000989 void consumeTouchModeEvent(bool inTouchMode) {
990 const InputEvent* event = consume();
991 ASSERT_NE(nullptr, event) << mName.c_str()
992 << ": consumer should have returned non-NULL event.";
993 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
994 << "Got " << inputEventTypeToString(event->getType())
995 << " event instead of TOUCH_MODE event";
996
997 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
998 << mName.c_str() << ": event displayId should always be NONE.";
999 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1000 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1001 }
1002
chaviwd1c23182019-12-20 18:44:56 -08001003 void assertNoEvents() {
1004 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001005 if (event == nullptr) {
1006 return;
1007 }
1008 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
1009 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1010 ADD_FAILURE() << "Received key event "
1011 << KeyEvent::actionToString(keyEvent.getAction());
1012 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
1013 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1014 ADD_FAILURE() << "Received motion event "
1015 << MotionEvent::actionToString(motionEvent.getAction());
1016 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
1017 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1018 ADD_FAILURE() << "Received focus event, hasFocus = "
1019 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -08001020 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
1021 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1022 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1023 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +00001024 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
1025 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1026 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1027 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001028 }
1029 FAIL() << mName.c_str()
1030 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001031 }
1032
1033 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1034
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001035 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1036
chaviwd1c23182019-12-20 18:44:56 -08001037protected:
1038 std::unique_ptr<InputConsumer> mConsumer;
1039 PreallocatedInputEventFactory mEventFactory;
1040
1041 std::string mName;
1042};
1043
chaviw3277faf2021-05-19 16:45:23 -05001044class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001045public:
1046 static const int32_t WIDTH = 600;
1047 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001048
Chris Yea209fde2020-07-22 13:54:51 -07001049 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001050 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001051 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001052 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001053 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001054 base::Result<std::unique_ptr<InputChannel>> channel =
1055 dispatcher->createInputChannel(name);
1056 token = (*channel)->getConnectionToken();
1057 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001058 }
1059
1060 inputApplicationHandle->updateInfo();
1061 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1062
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001063 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001064 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001065 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001066 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001067 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001068 mInfo.frameLeft = 0;
1069 mInfo.frameTop = 0;
1070 mInfo.frameRight = WIDTH;
1071 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001072 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001073 mInfo.globalScaleFactor = 1.0;
1074 mInfo.touchableRegion.clear();
1075 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001076 mInfo.ownerPid = WINDOW_PID;
1077 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001078 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001079 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001080 }
1081
Arthur Hungabbb9d82021-09-01 14:52:30 +00001082 sp<FakeWindowHandle> clone(
1083 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001084 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001085 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001086 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1087 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001088 return handle;
1089 }
1090
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001091 void setTouchable(bool touchable) {
1092 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1093 }
chaviwd1c23182019-12-20 18:44:56 -08001094
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001095 void setFocusable(bool focusable) {
1096 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1097 }
1098
1099 void setVisible(bool visible) {
1100 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1101 }
Vishnu Nair958da932020-08-21 17:12:37 -07001102
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001103 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001104 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001105 }
1106
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001107 void setPaused(bool paused) {
1108 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1109 }
1110
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001111 void setPreventSplitting(bool preventSplitting) {
1112 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001113 }
1114
1115 void setSlippery(bool slippery) {
1116 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1117 }
1118
1119 void setWatchOutsideTouch(bool watchOutside) {
1120 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1121 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001122
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001123 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1124
1125 void setInterceptsStylus(bool interceptsStylus) {
1126 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1127 }
1128
1129 void setDropInput(bool dropInput) {
1130 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1131 }
1132
1133 void setDropInputIfObscured(bool dropInputIfObscured) {
1134 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1135 }
1136
1137 void setNoInputChannel(bool noInputChannel) {
1138 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1139 }
1140
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001141 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1142
chaviw3277faf2021-05-19 16:45:23 -05001143 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001144
Bernardo Rufino7393d172021-02-26 13:56:11 +00001145 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1146
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001147 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001148 mInfo.frameLeft = frame.left;
1149 mInfo.frameTop = frame.top;
1150 mInfo.frameRight = frame.right;
1151 mInfo.frameBottom = frame.bottom;
1152 mInfo.touchableRegion.clear();
1153 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001154
1155 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1156 ui::Transform translate;
1157 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1158 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001159 }
1160
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001161 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1162
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001163 void setIsWallpaper(bool isWallpaper) {
1164 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1165 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001166
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001167 void setDupTouchToWallpaper(bool hasWallpaper) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1169 }
chaviwd1c23182019-12-20 18:44:56 -08001170
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001171 void setTrustedOverlay(bool trustedOverlay) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1173 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001174
chaviw9eaa22c2020-07-01 16:21:27 -07001175 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1176 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1177 }
1178
1179 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001180
yunho.shinf4a80b82020-11-16 21:13:57 +09001181 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1182
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001183 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1184 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1185 expectedFlags);
1186 }
1187
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001188 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1189 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1190 }
1191
Svet Ganov5d3bc372020-01-26 23:11:07 -08001192 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001193 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001194 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1195 expectedFlags);
1196 }
1197
1198 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001199 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001200 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1201 expectedFlags);
1202 }
1203
1204 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001205 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001206 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1207 }
1208
1209 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1210 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001211 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1212 expectedFlags);
1213 }
1214
Svet Ganov5d3bc372020-01-26 23:11:07 -08001215 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001216 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1217 int32_t expectedFlags = 0) {
1218 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1219 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001220 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1221 }
1222
1223 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001224 int32_t expectedFlags = 0) {
1225 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1226 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001227 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1228 }
1229
1230 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001231 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001232 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1233 expectedFlags);
1234 }
1235
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001236 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1237 int32_t expectedFlags = 0) {
1238 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1239 expectedFlags);
1240 }
1241
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001242 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1243 int32_t expectedFlags = 0) {
1244 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001245 ASSERT_NE(nullptr, event);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001246 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1247 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1248 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1249 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1250 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1251 }
1252
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001253 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1254 ASSERT_NE(mInputReceiver, nullptr)
1255 << "Cannot consume events from a window with no receiver";
1256 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1257 }
1258
Prabir Pradhan99987712020-11-10 18:43:05 -08001259 void consumeCaptureEvent(bool hasCapture) {
1260 ASSERT_NE(mInputReceiver, nullptr)
1261 << "Cannot consume events from a window with no receiver";
1262 mInputReceiver->consumeCaptureEvent(hasCapture);
1263 }
1264
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001265 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1266 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001267 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001268 ASSERT_THAT(*motionEvent, matcher);
1269 }
1270
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001271 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1272 std::optional<int32_t> expectedDisplayId,
1273 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001274 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1275 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1276 expectedFlags);
1277 }
1278
arthurhungb89ccb02020-12-30 16:19:01 +08001279 void consumeDragEvent(bool isExiting, float x, float y) {
1280 mInputReceiver->consumeDragEvent(isExiting, x, y);
1281 }
1282
Antonio Kantekf16f2832021-09-28 04:39:20 +00001283 void consumeTouchModeEvent(bool inTouchMode) {
1284 ASSERT_NE(mInputReceiver, nullptr)
1285 << "Cannot consume events from a window with no receiver";
1286 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1287 }
1288
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001289 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001290 if (mInputReceiver == nullptr) {
1291 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1292 return std::nullopt;
1293 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001294 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001295 }
1296
1297 void finishEvent(uint32_t sequenceNum) {
1298 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1299 mInputReceiver->finishEvent(sequenceNum);
1300 }
1301
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001302 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1303 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1304 mInputReceiver->sendTimeline(inputEventId, timeline);
1305 }
1306
chaviwaf87b3e2019-10-01 16:59:28 -07001307 InputEvent* consume() {
1308 if (mInputReceiver == nullptr) {
1309 return nullptr;
1310 }
1311 return mInputReceiver->consume();
1312 }
1313
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001314 MotionEvent* consumeMotion() {
1315 InputEvent* event = consume();
1316 if (event == nullptr) {
1317 ADD_FAILURE() << "Consume failed : no event";
1318 return nullptr;
1319 }
1320 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1321 ADD_FAILURE() << "Instead of motion event, got "
1322 << inputEventTypeToString(event->getType());
1323 return nullptr;
1324 }
1325 return static_cast<MotionEvent*>(event);
1326 }
1327
Arthur Hungb92218b2018-08-14 12:00:21 +08001328 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001329 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001330 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001331 return; // Can't receive events if the window does not have input channel
1332 }
1333 ASSERT_NE(nullptr, mInputReceiver)
1334 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001335 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001336 }
1337
chaviwaf87b3e2019-10-01 16:59:28 -07001338 sp<IBinder> getToken() { return mInfo.token; }
1339
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001340 const std::string& getName() { return mName; }
1341
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001342 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1343 mInfo.ownerPid = ownerPid;
1344 mInfo.ownerUid = ownerUid;
1345 }
1346
Prabir Pradhanedd96402022-02-15 01:46:16 -08001347 int32_t getPid() const { return mInfo.ownerPid; }
1348
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001349 void destroyReceiver() { mInputReceiver = nullptr; }
1350
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001351 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1352
chaviwd1c23182019-12-20 18:44:56 -08001353private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001354 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001355 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001356 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001357};
1358
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001359std::atomic<int32_t> FakeWindowHandle::sId{1};
1360
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001361static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001362 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001363 int32_t displayId = ADISPLAY_ID_NONE,
1364 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001365 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001366 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1367 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001368 KeyEvent event;
1369 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1370
1371 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001372 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001373 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1374 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001375
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001376 if (!allowKeyRepeat) {
1377 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1378 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001379 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001380 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001381}
1382
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001383static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001384 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001385 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1386}
1387
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001388// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1389// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1390// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001391static InputEventInjectionResult injectKeyDownNoRepeat(
1392 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001393 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1394 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1395 /* allowKeyRepeat */ false);
1396}
1397
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001398static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001399 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001400 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1401}
1402
Garfield Tandf26e862020-07-01 20:18:19 -07001403class PointerBuilder {
1404public:
1405 PointerBuilder(int32_t id, int32_t toolType) {
1406 mProperties.clear();
1407 mProperties.id = id;
1408 mProperties.toolType = toolType;
1409 mCoords.clear();
1410 }
1411
1412 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1413
1414 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1415
1416 PointerBuilder& axis(int32_t axis, float value) {
1417 mCoords.setAxisValue(axis, value);
1418 return *this;
1419 }
1420
1421 PointerProperties buildProperties() const { return mProperties; }
1422
1423 PointerCoords buildCoords() const { return mCoords; }
1424
1425private:
1426 PointerProperties mProperties;
1427 PointerCoords mCoords;
1428};
1429
1430class MotionEventBuilder {
1431public:
1432 MotionEventBuilder(int32_t action, int32_t source) {
1433 mAction = action;
1434 mSource = source;
1435 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1436 }
1437
1438 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1439 mEventTime = eventTime;
1440 return *this;
1441 }
1442
1443 MotionEventBuilder& displayId(int32_t displayId) {
1444 mDisplayId = displayId;
1445 return *this;
1446 }
1447
1448 MotionEventBuilder& actionButton(int32_t actionButton) {
1449 mActionButton = actionButton;
1450 return *this;
1451 }
1452
arthurhung6d4bed92021-03-17 11:59:33 +08001453 MotionEventBuilder& buttonState(int32_t buttonState) {
1454 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001455 return *this;
1456 }
1457
1458 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1459 mRawXCursorPosition = rawXCursorPosition;
1460 return *this;
1461 }
1462
1463 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1464 mRawYCursorPosition = rawYCursorPosition;
1465 return *this;
1466 }
1467
1468 MotionEventBuilder& pointer(PointerBuilder pointer) {
1469 mPointers.push_back(pointer);
1470 return *this;
1471 }
1472
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001473 MotionEventBuilder& addFlag(uint32_t flags) {
1474 mFlags |= flags;
1475 return *this;
1476 }
1477
Garfield Tandf26e862020-07-01 20:18:19 -07001478 MotionEvent build() {
1479 std::vector<PointerProperties> pointerProperties;
1480 std::vector<PointerCoords> pointerCoords;
1481 for (const PointerBuilder& pointer : mPointers) {
1482 pointerProperties.push_back(pointer.buildProperties());
1483 pointerCoords.push_back(pointer.buildCoords());
1484 }
1485
1486 // Set mouse cursor position for the most common cases to avoid boilerplate.
1487 if (mSource == AINPUT_SOURCE_MOUSE &&
1488 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1489 mPointers.size() == 1) {
1490 mRawXCursorPosition = pointerCoords[0].getX();
1491 mRawYCursorPosition = pointerCoords[0].getY();
1492 }
1493
1494 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001495 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001496 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001497 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001498 mButtonState, MotionClassification::NONE, identityTransform,
1499 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001500 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1501 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001502
1503 return event;
1504 }
1505
1506private:
1507 int32_t mAction;
1508 int32_t mSource;
1509 nsecs_t mEventTime;
1510 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1511 int32_t mActionButton{0};
1512 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001513 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001514 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1515 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1516
1517 std::vector<PointerBuilder> mPointers;
1518};
1519
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001520static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001521 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001522 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001523 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1524 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1525 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1526 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001527}
1528
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001529static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001530 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001531 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001532 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001533 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1534 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001535 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001536 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1537 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001538 MotionEvent event = MotionEventBuilder(action, source)
1539 .displayId(displayId)
1540 .eventTime(eventTime)
1541 .rawXCursorPosition(cursorPosition.x)
1542 .rawYCursorPosition(cursorPosition.y)
1543 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1544 .x(position.x)
1545 .y(position.y))
1546 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001547
1548 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001549 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1550 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001551}
1552
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001553static InputEventInjectionResult injectMotionDown(
1554 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1555 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001556 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001557}
1558
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001559static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001560 int32_t source, int32_t displayId,
1561 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001562 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001563}
1564
Jackal Guof9696682018-10-05 12:23:23 +08001565static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1566 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1567 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001568 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1569 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1570 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001571
1572 return args;
1573}
1574
chaviwd1c23182019-12-20 18:44:56 -08001575static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1576 const std::vector<PointF>& points) {
1577 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001578 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1579 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1580 }
1581
chaviwd1c23182019-12-20 18:44:56 -08001582 PointerProperties pointerProperties[pointerCount];
1583 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001584
chaviwd1c23182019-12-20 18:44:56 -08001585 for (size_t i = 0; i < pointerCount; i++) {
1586 pointerProperties[i].clear();
1587 pointerProperties[i].id = i;
1588 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001589
chaviwd1c23182019-12-20 18:44:56 -08001590 pointerCoords[i].clear();
1591 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1592 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1593 }
Jackal Guof9696682018-10-05 12:23:23 +08001594
1595 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1596 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001597 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001598 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1599 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001600 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1601 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001602 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1603 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001604
1605 return args;
1606}
1607
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001608static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1609 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1610}
1611
chaviwd1c23182019-12-20 18:44:56 -08001612static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1613 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1614}
1615
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001616static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1617 const PointerCaptureRequest& request) {
1618 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001619}
1620
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001621/**
1622 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1623 * broken channel.
1624 */
1625TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1627 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001628 sp<FakeWindowHandle>::make(application, mDispatcher,
1629 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001630
1631 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1632
1633 // Window closes its channel, but the window remains.
1634 window->destroyReceiver();
1635 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1636}
1637
Arthur Hungb92218b2018-08-14 12:00:21 +08001638TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001640 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1641 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001642
Arthur Hung72d8dc32020-03-28 00:48:39 +00001643 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1645 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001647
1648 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001649 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001650}
1651
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001652TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001654 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1655 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001656
1657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1658 // Inject a MotionEvent to an unknown display.
1659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1660 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1662
1663 // Window should receive motion event.
1664 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1665}
1666
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001667/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001668 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001669 * This test serves as a sanity check for the next test, where setInputWindows is
1670 * called twice.
1671 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001672TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1675 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001676 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677
1678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001680 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1681 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001683
1684 // Window should receive motion event.
1685 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1686}
1687
1688/**
1689 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 */
1691TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001693 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1694 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696
1697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001700 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1701 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703
1704 // Window should receive motion event.
1705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1706}
1707
Arthur Hungb92218b2018-08-14 12:00:21 +08001708// The foreground window should receive the first touch down event.
1709TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001711 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001712 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001713 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001714 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001715
Arthur Hung72d8dc32020-03-28 00:48:39 +00001716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1718 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001720
1721 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001722 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001723 windowSecond->assertNoEvents();
1724}
1725
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001726/**
1727 * Two windows: A top window, and a wallpaper behind the window.
1728 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1729 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001730 * 1. foregroundWindow <-- dup touch to wallpaper
1731 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001732 */
1733TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1734 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1735 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001736 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001737 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001738 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001739 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001740 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001741 constexpr int expectedWallpaperFlags =
1742 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1743
1744 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1746 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1747 {100, 200}))
1748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1749
1750 // Both foreground window and its wallpaper should receive the touch down
1751 foregroundWindow->consumeMotionDown();
1752 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1753
1754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1755 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1756 ADISPLAY_ID_DEFAULT, {110, 200}))
1757 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1758
1759 foregroundWindow->consumeMotionMove();
1760 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1761
1762 // Now the foreground window goes away, but the wallpaper stays
1763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1764 foregroundWindow->consumeMotionCancel();
1765 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1766 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1767}
1768
1769/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001770 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1771 * with the following differences:
1772 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1773 * clean up the connection.
1774 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1775 * Ensure that there's no crash in the dispatcher.
1776 */
1777TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1779 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001780 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001781 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001782 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001783 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001784 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001785 constexpr int expectedWallpaperFlags =
1786 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1787
1788 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1790 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1791 {100, 200}))
1792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1793
1794 // Both foreground window and its wallpaper should receive the touch down
1795 foregroundWindow->consumeMotionDown();
1796 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1797
1798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1799 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1800 ADISPLAY_ID_DEFAULT, {110, 200}))
1801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1802
1803 foregroundWindow->consumeMotionMove();
1804 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1805
1806 // Wallpaper closes its channel, but the window remains.
1807 wallpaperWindow->destroyReceiver();
1808 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1809
1810 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1811 // is no longer valid.
1812 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1813 foregroundWindow->consumeMotionCancel();
1814}
1815
1816/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001817 * A single window that receives touch (on top), and a wallpaper window underneath it.
1818 * The top window gets a multitouch gesture.
1819 * Ensure that wallpaper gets the same gesture.
1820 */
1821TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1823 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001824 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001825 window->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001826
1827 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001828 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001829 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001830 constexpr int expectedWallpaperFlags =
1831 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1832
1833 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1834
1835 // Touch down on top window
1836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1837 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1838 {100, 100}))
1839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1840
1841 // Both top window and its wallpaper should receive the touch down
1842 window->consumeMotionDown();
1843 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1844
1845 // Second finger down on the top window
1846 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001847 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001848 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1849 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1850 .x(100)
1851 .y(100))
1852 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1853 .x(150)
1854 .y(150))
1855 .build();
1856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1857 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1858 InputEventInjectionSync::WAIT_FOR_RESULT))
1859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1860
1861 window->consumeMotionPointerDown(1 /* pointerIndex */);
1862 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1863 expectedWallpaperFlags);
1864 window->assertNoEvents();
1865 wallpaperWindow->assertNoEvents();
1866}
1867
1868/**
1869 * Two windows: a window on the left and window on the right.
1870 * A third window, wallpaper, is behind both windows, and spans both top windows.
1871 * The first touch down goes to the left window. A second pointer touches down on the right window.
1872 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1873 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1874 * ACTION_POINTER_DOWN(1).
1875 */
1876TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1878 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001879 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001880 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001881 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882
1883 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001884 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001886 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001887
1888 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001889 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001891 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001892 constexpr int expectedWallpaperFlags =
1893 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1894
1895 mDispatcher->setInputWindows(
1896 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1897
1898 // Touch down on left window
1899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1900 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1901 {100, 100}))
1902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1903
1904 // Both foreground window and its wallpaper should receive the touch down
1905 leftWindow->consumeMotionDown();
1906 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1907
1908 // Second finger down on the right window
1909 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001910 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1912 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1913 .x(100)
1914 .y(100))
1915 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1916 .x(300)
1917 .y(100))
1918 .build();
1919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1920 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1921 InputEventInjectionSync::WAIT_FOR_RESULT))
1922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1923
1924 leftWindow->consumeMotionMove();
1925 // Since the touch is split, right window gets ACTION_DOWN
1926 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1927 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1928 expectedWallpaperFlags);
1929
1930 // Now, leftWindow, which received the first finger, disappears.
1931 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1932 leftWindow->consumeMotionCancel();
1933 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1934 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1935
1936 // The pointer that's still down on the right window moves, and goes to the right window only.
1937 // As far as the dispatcher's concerned though, both pointers are still present.
1938 const MotionEvent secondFingerMoveEvent =
1939 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1940 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1941 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1942 .x(100)
1943 .y(100))
1944 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1945 .x(310)
1946 .y(110))
1947 .build();
1948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1949 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1950 InputEventInjectionSync::WAIT_FOR_RESULT));
1951 rightWindow->consumeMotionMove();
1952
1953 leftWindow->assertNoEvents();
1954 rightWindow->assertNoEvents();
1955 wallpaperWindow->assertNoEvents();
1956}
1957
Arthur Hung74c248d2022-11-23 07:09:59 +00001958TEST_F(InputDispatcherTest, WallpaperWindowReceivesMultiTouch) {
1959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1960 sp<FakeWindowHandle> window =
1961 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1962 window->setDupTouchToWallpaper(true);
1963
1964 sp<FakeWindowHandle> wallpaperWindow =
1965 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1966 wallpaperWindow->setIsWallpaper(true);
1967 constexpr int expectedWallpaperFlags =
1968 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1969 wallpaperWindow->setPreventSplitting(true);
1970
1971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1972
1973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1974 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1975 {50, 50}))
1976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1977 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1978 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1979
1980 const MotionEvent secondFingerDownEvent =
1981 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1982 .displayId(ADISPLAY_ID_DEFAULT)
1983 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1984 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
1985 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
1986 .build();
1987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1988 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1989 InputEventInjectionSync::WAIT_FOR_RESULT))
1990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1991
1992 window->consumeMotionPointerDown(1);
1993 wallpaperWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1994
1995 const MotionEvent secondFingerUpEvent =
1996 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
1997 .displayId(ADISPLAY_ID_DEFAULT)
1998 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1999 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
2000 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
2001 .build();
2002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2003 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2004 InputEventInjectionSync::WAIT_FOR_RESULT))
2005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2006 window->consumeMotionPointerUp(1);
2007 wallpaperWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2008
2009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2010 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
2011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2012 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2013 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2014}
2015
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002016/**
2017 * On the display, have a single window, and also an area where there's no window.
2018 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2019 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2020 */
2021TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2023 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002024 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002025
2026 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
2027 NotifyMotionArgs args;
2028
2029 // Touch down on the empty space
2030 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
2031
2032 mDispatcher->waitForIdle();
2033 window->assertNoEvents();
2034
2035 // Now touch down on the window with another pointer
2036 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
2037 mDispatcher->waitForIdle();
2038 window->consumeMotionDown();
2039}
2040
2041/**
2042 * Same test as above, but instead of touching the empty space, the first touch goes to
2043 * non-touchable window.
2044 */
2045TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2046 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2047 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002048 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002049 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2050 window1->setTouchable(false);
2051 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002052 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002053 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2054
2055 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2056
2057 NotifyMotionArgs args;
2058 // Touch down on the non-touchable window
2059 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2060
2061 mDispatcher->waitForIdle();
2062 window1->assertNoEvents();
2063 window2->assertNoEvents();
2064
2065 // Now touch down on the window with another pointer
2066 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2067 mDispatcher->waitForIdle();
2068 window2->consumeMotionDown();
2069}
2070
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002071/**
2072 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2073 * to the event time of the first ACTION_DOWN sent to the particular window.
2074 */
2075TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2077 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002078 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002079 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2080 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002081 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002082 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2083
2084 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2085
2086 NotifyMotionArgs args;
2087 // Touch down on the first window
2088 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2089
2090 mDispatcher->waitForIdle();
2091 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002092 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002093 window2->assertNoEvents();
2094 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2095 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2096 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2097
2098 // Now touch down on the window with another pointer
2099 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2100 mDispatcher->waitForIdle();
2101 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002102 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002103 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2104 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2105 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2106 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2107
2108 // Now move the pointer on the second window
2109 mDispatcher->notifyMotion(
2110 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
2111 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002112 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002113
2114 // Now add new touch down on the second window
2115 mDispatcher->notifyMotion(
2116 &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
2117 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002118 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002119
2120 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2121 window1->consumeMotionMove();
2122 window1->assertNoEvents();
2123
2124 // Now move the pointer on the first window
2125 mDispatcher->notifyMotion(
2126 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
2127 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002128 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002129
2130 mDispatcher->notifyMotion(&(
2131 args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
2132 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002133 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002134}
2135
Garfield Tandf26e862020-07-01 20:18:19 -07002136TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002138 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002139 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002140 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002141 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002142 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002143 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002144
2145 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2146
2147 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
2148
2149 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002151 injectMotionEvent(mDispatcher,
2152 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2153 AINPUT_SOURCE_MOUSE)
2154 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2155 .x(900)
2156 .y(400))
2157 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002158 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Sam Dubey39d37cf2022-12-07 18:05:35 +00002159 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
Garfield Tandf26e862020-07-01 20:18:19 -07002160
2161 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002163 injectMotionEvent(mDispatcher,
2164 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2165 AINPUT_SOURCE_MOUSE)
2166 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2167 .x(300)
2168 .y(400))
2169 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002170 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2171 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Sam Dubey39d37cf2022-12-07 18:05:35 +00002172 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
Garfield Tandf26e862020-07-01 20:18:19 -07002173
2174 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002176 injectMotionEvent(mDispatcher,
2177 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2178 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2179 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2180 .x(300)
2181 .y(400))
2182 .build()));
2183 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2184
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002186 injectMotionEvent(mDispatcher,
2187 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2188 AINPUT_SOURCE_MOUSE)
2189 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2190 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2191 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2192 .x(300)
2193 .y(400))
2194 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002195 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07002196
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002198 injectMotionEvent(mDispatcher,
2199 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2200 AINPUT_SOURCE_MOUSE)
2201 .buttonState(0)
2202 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2203 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2204 .x(300)
2205 .y(400))
2206 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002207 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07002208
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002210 injectMotionEvent(mDispatcher,
2211 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2212 .buttonState(0)
2213 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2214 .x(300)
2215 .y(400))
2216 .build()));
2217 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2218
2219 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002221 injectMotionEvent(mDispatcher,
2222 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2223 AINPUT_SOURCE_MOUSE)
2224 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2225 .x(900)
2226 .y(400))
2227 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002228 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2229 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Sam Dubey39d37cf2022-12-07 18:05:35 +00002230 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002231
2232 // No more events
2233 windowLeft->assertNoEvents();
2234 windowRight->assertNoEvents();
2235}
2236
2237TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
2238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2239
2240 sp<FakeWindowHandle> spyWindow =
2241 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2242 spyWindow->setFrame(Rect(0, 0, 600, 800));
2243 spyWindow->setTrustedOverlay(true);
2244 spyWindow->setSpy(true);
2245 sp<FakeWindowHandle> window =
2246 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2247 window->setFrame(Rect(0, 0, 600, 800));
2248
2249 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2250 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2251
2252 // Send mouse cursor to the window
2253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2254 injectMotionEvent(mDispatcher,
2255 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2256 AINPUT_SOURCE_MOUSE)
2257 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2258 .x(100)
2259 .y(100))
2260 .build()));
2261
2262 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2263 WithSource(AINPUT_SOURCE_MOUSE)));
2264 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2265 WithSource(AINPUT_SOURCE_MOUSE)));
2266
2267 window->assertNoEvents();
2268 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07002269}
2270
2271// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
2272// directly in this test.
2273TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002275 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002276 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002277 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002278
2279 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2280
2281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2282
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002284 injectMotionEvent(mDispatcher,
2285 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2286 AINPUT_SOURCE_MOUSE)
2287 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2288 .x(300)
2289 .y(400))
2290 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002291 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Sam Dubey39d37cf2022-12-07 18:05:35 +00002292
Garfield Tandf26e862020-07-01 20:18:19 -07002293 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002295 injectMotionEvent(mDispatcher,
2296 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2297 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2298 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2299 .x(300)
2300 .y(400))
2301 .build()));
2302 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2303
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002305 injectMotionEvent(mDispatcher,
2306 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2307 AINPUT_SOURCE_MOUSE)
2308 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2309 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2310 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2311 .x(300)
2312 .y(400))
2313 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002314 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07002315
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002317 injectMotionEvent(mDispatcher,
2318 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2319 AINPUT_SOURCE_MOUSE)
2320 .buttonState(0)
2321 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2322 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2323 .x(300)
2324 .y(400))
2325 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002326 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07002327
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002329 injectMotionEvent(mDispatcher,
2330 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2331 .buttonState(0)
2332 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2333 .x(300)
2334 .y(400))
2335 .build()));
2336 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2337
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002339 injectMotionEvent(mDispatcher,
2340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
2341 AINPUT_SOURCE_MOUSE)
2342 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2343 .x(300)
2344 .y(400))
2345 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002346 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
Garfield Tandf26e862020-07-01 20:18:19 -07002347}
2348
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002349/**
2350 * Inject a mouse hover event followed by a tap from touchscreen.
Sam Dubey39d37cf2022-12-07 18:05:35 +00002351 * In the current implementation, the tap does not cause a HOVER_EXIT event.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002352 */
2353TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
2354 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2355 sp<FakeWindowHandle> window =
2356 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2357 window->setFrame(Rect(0, 0, 100, 100));
2358
2359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2360
2361 // Inject a hover_move from mouse.
2362 NotifyMotionArgs motionArgs =
2363 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
2364 ADISPLAY_ID_DEFAULT, {{50, 50}});
2365 motionArgs.xCursorPosition = 50;
2366 motionArgs.yCursorPosition = 50;
2367 mDispatcher->notifyMotion(&motionArgs);
2368 ASSERT_NO_FATAL_FAILURE(
2369 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2370 WithSource(AINPUT_SOURCE_MOUSE))));
Sam Dubey39d37cf2022-12-07 18:05:35 +00002371 ASSERT_NO_FATAL_FAILURE(
2372 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2373 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002374
2375 // Tap on the window
2376 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2377 ADISPLAY_ID_DEFAULT, {{10, 10}});
2378 mDispatcher->notifyMotion(&motionArgs);
2379 ASSERT_NO_FATAL_FAILURE(
2380 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2381 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
2382
2383 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2384 ADISPLAY_ID_DEFAULT, {{10, 10}});
2385 mDispatcher->notifyMotion(&motionArgs);
2386 ASSERT_NO_FATAL_FAILURE(
2387 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
2388 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
2389}
2390
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002391TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
2392 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2393 sp<FakeWindowHandle> windowDefaultDisplay =
2394 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
2395 ADISPLAY_ID_DEFAULT);
2396 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
2397 sp<FakeWindowHandle> windowSecondDisplay =
2398 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
2399 SECOND_DISPLAY_ID);
2400 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
2401
2402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
2403 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
2404
2405 // Set cursor position in window in default display and check that hover enter and move
2406 // events are generated.
2407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2408 injectMotionEvent(mDispatcher,
2409 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2410 AINPUT_SOURCE_MOUSE)
2411 .displayId(ADISPLAY_ID_DEFAULT)
2412 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2413 .x(300)
2414 .y(600))
2415 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002416 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Sam Dubey39d37cf2022-12-07 18:05:35 +00002417 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002418
2419 // Remove all windows in secondary display and check that no event happens on window in
2420 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002421 mDispatcher->setInputWindows(
2422 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002423 windowDefaultDisplay->assertNoEvents();
2424
2425 // Move cursor position in window in default display and check that only hover move
2426 // event is generated and not hover enter event.
2427 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
2428 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
2429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2430 injectMotionEvent(mDispatcher,
2431 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2432 AINPUT_SOURCE_MOUSE)
2433 .displayId(ADISPLAY_ID_DEFAULT)
2434 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2435 .x(400)
2436 .y(700))
2437 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002438 windowDefaultDisplay->consumeMotionEvent(
2439 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2440 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002441 windowDefaultDisplay->assertNoEvents();
2442}
2443
Garfield Tan00f511d2019-06-12 16:55:40 -07002444TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07002445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07002446
2447 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002448 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002449 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002450 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002451 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002452 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002453
2454 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2455
Arthur Hung72d8dc32020-03-28 00:48:39 +00002456 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07002457
2458 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
2459 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07002461 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002462 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002463 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002464 windowRight->assertNoEvents();
2465}
2466
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002467TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002469 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2470 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07002471 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002472
Arthur Hung72d8dc32020-03-28 00:48:39 +00002473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002474 setFocusedWindow(window);
2475
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002476 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002477
2478 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2479 mDispatcher->notifyKey(&keyArgs);
2480
2481 // Window should receive key down event.
2482 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2483
2484 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
2485 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002486 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002487 mDispatcher->notifyDeviceReset(&args);
2488 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2489 AKEY_EVENT_FLAG_CANCELED);
2490}
2491
2492TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002494 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2495 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002496
Arthur Hung72d8dc32020-03-28 00:48:39 +00002497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002498
2499 NotifyMotionArgs motionArgs =
2500 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2501 ADISPLAY_ID_DEFAULT);
2502 mDispatcher->notifyMotion(&motionArgs);
2503
2504 // Window should receive motion down event.
2505 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2506
2507 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
2508 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002509 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002510 mDispatcher->notifyDeviceReset(&args);
2511 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
2512 0 /*expectedFlags*/);
2513}
2514
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002515TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
2516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002517 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2518 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002519 window->setFocusable(true);
2520
2521 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2522 setFocusedWindow(window);
2523
2524 window->consumeFocusEvent(true);
2525
2526 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2527 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
2528 const nsecs_t injectTime = keyArgs.eventTime;
2529 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
2530 mDispatcher->notifyKey(&keyArgs);
2531 // The dispatching time should be always greater than or equal to intercept key timeout.
2532 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2533 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
2534 std::chrono::nanoseconds(interceptKeyTimeout).count());
2535}
2536
2537TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
2538 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002539 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2540 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002541 window->setFocusable(true);
2542
2543 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2544 setFocusedWindow(window);
2545
2546 window->consumeFocusEvent(true);
2547
2548 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2549 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2550 mFakePolicy->setInterceptKeyTimeout(150ms);
2551 mDispatcher->notifyKey(&keyDown);
2552 mDispatcher->notifyKey(&keyUp);
2553
2554 // Window should receive key event immediately when same key up.
2555 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2556 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
2557}
2558
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002559/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08002560 * Two windows. First is a regular window. Second does not overlap with the first, and has
2561 * WATCH_OUTSIDE_TOUCH.
2562 * Both windows are owned by the same UID.
2563 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
2564 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
2565 */
2566TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
2567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2568 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2569 "First Window", ADISPLAY_ID_DEFAULT);
2570 window->setFrame(Rect{0, 0, 100, 100});
2571
2572 sp<FakeWindowHandle> outsideWindow =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2574 ADISPLAY_ID_DEFAULT);
2575 outsideWindow->setFrame(Rect{100, 100, 200, 200});
2576 outsideWindow->setWatchOutsideTouch(true);
2577 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
2578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
2579
2580 // Tap on first window.
2581 NotifyMotionArgs motionArgs =
2582 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2583 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
2584 mDispatcher->notifyMotion(&motionArgs);
2585 window->consumeMotionDown();
2586 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
2587 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
2588 outsideWindow->consumeMotionEvent(
2589 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
2590}
2591
2592/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002593 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
2594 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
2595 * ACTION_OUTSIDE event is sent per gesture.
2596 */
2597TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
2598 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
2599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002600 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2601 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002602 window->setWatchOutsideTouch(true);
2603 window->setFrame(Rect{0, 0, 100, 100});
2604 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002605 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2606 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002607 secondWindow->setFrame(Rect{100, 100, 200, 200});
2608 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002609 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
2610 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002611 thirdWindow->setFrame(Rect{200, 200, 300, 300});
2612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
2613
2614 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
2615 NotifyMotionArgs motionArgs =
2616 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2617 ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
2618 mDispatcher->notifyMotion(&motionArgs);
2619 window->assertNoEvents();
2620 secondWindow->assertNoEvents();
2621
2622 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
2623 // Now, `window` should get ACTION_OUTSIDE.
2624 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2625 {PointF{-10, -10}, PointF{105, 105}});
2626 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08002627 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
2628 window->consumeMotionEvent(
2629 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002630 secondWindow->consumeMotionDown();
2631 thirdWindow->assertNoEvents();
2632
2633 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
2634 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
2635 motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2636 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
2637 mDispatcher->notifyMotion(&motionArgs);
2638 window->assertNoEvents();
2639 secondWindow->consumeMotionMove();
2640 thirdWindow->consumeMotionDown();
2641}
2642
Prabir Pradhan814fe082022-07-22 20:22:18 +00002643TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
2644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002645 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2646 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00002647 window->setFocusable(true);
2648
2649 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
2650 setFocusedWindow(window);
2651
2652 window->consumeFocusEvent(true);
2653
2654 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2655 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2656 mDispatcher->notifyKey(&keyDown);
2657 mDispatcher->notifyKey(&keyUp);
2658
2659 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2660 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
2661
2662 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
2663 mDispatcher->onWindowInfosChanged({}, {});
2664
2665 window->consumeFocusEvent(false);
2666
2667 mDispatcher->notifyKey(&keyDown);
2668 mDispatcher->notifyKey(&keyUp);
2669 window->assertNoEvents();
2670}
2671
Arthur Hung96483742022-11-15 03:30:48 +00002672TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
2673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2675 "Fake Window", ADISPLAY_ID_DEFAULT);
2676 // Ensure window is non-split and have some transform.
2677 window->setPreventSplitting(true);
2678 window->setWindowOffset(20, 40);
2679 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
2680
2681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2682 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2683 {50, 50}))
2684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2685 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2686
2687 const MotionEvent secondFingerDownEvent =
2688 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2689 .displayId(ADISPLAY_ID_DEFAULT)
2690 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2691 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
2692 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
2693 .x(-30)
2694 .y(-50))
2695 .build();
2696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2697 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2698 InputEventInjectionSync::WAIT_FOR_RESULT))
2699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2700
2701 const MotionEvent* event = window->consumeMotion();
2702 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
2703 EXPECT_EQ(70, event->getX(0)); // 50 + 20
2704 EXPECT_EQ(90, event->getY(0)); // 50 + 40
2705 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
2706 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
2707}
2708
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002709/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002710 * Ensure the correct coordinate spaces are used by InputDispatcher.
2711 *
2712 * InputDispatcher works in the display space, so its coordinate system is relative to the display
2713 * panel. Windows get events in the window space, and get raw coordinates in the logical display
2714 * space.
2715 */
2716class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
2717public:
2718 void SetUp() override {
2719 InputDispatcherTest::SetUp();
2720 mDisplayInfos.clear();
2721 mWindowInfos.clear();
2722 }
2723
2724 void addDisplayInfo(int displayId, const ui::Transform& transform) {
2725 gui::DisplayInfo info;
2726 info.displayId = displayId;
2727 info.transform = transform;
2728 mDisplayInfos.push_back(std::move(info));
2729 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2730 }
2731
2732 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
2733 mWindowInfos.push_back(*windowHandle->getInfo());
2734 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2735 }
2736
2737 // Set up a test scenario where the display has a scaled projection and there are two windows
2738 // on the display.
2739 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
2740 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
2741 // respectively.
2742 ui::Transform displayTransform;
2743 displayTransform.set(2, 0, 0, 4);
2744 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
2745
2746 std::shared_ptr<FakeApplicationHandle> application =
2747 std::make_shared<FakeApplicationHandle>();
2748
2749 // Add two windows to the display. Their frames are represented in the display space.
2750 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002751 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2752 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002753 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
2754 addWindow(firstWindow);
2755
2756 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002757 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2758 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002759 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
2760 addWindow(secondWindow);
2761 return {std::move(firstWindow), std::move(secondWindow)};
2762 }
2763
2764private:
2765 std::vector<gui::DisplayInfo> mDisplayInfos;
2766 std::vector<gui::WindowInfo> mWindowInfos;
2767};
2768
2769TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
2770 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2771 // Send down to the first window. The point is represented in the display space. The point is
2772 // selected so that if the hit test was done with the transform applied to it, then it would
2773 // end up in the incorrect window.
2774 NotifyMotionArgs downMotionArgs =
2775 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2776 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
2777 mDispatcher->notifyMotion(&downMotionArgs);
2778
2779 firstWindow->consumeMotionDown();
2780 secondWindow->assertNoEvents();
2781}
2782
2783// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
2784// the event should be treated as being in the logical display space.
2785TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
2786 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2787 // Send down to the first window. The point is represented in the logical display space. The
2788 // point is selected so that if the hit test was done in logical display space, then it would
2789 // end up in the incorrect window.
2790 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2791 PointF{75 * 2, 55 * 4});
2792
2793 firstWindow->consumeMotionDown();
2794 secondWindow->assertNoEvents();
2795}
2796
Prabir Pradhandaa2f142021-12-10 09:30:08 +00002797// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
2798// event should be treated as being in the logical display space.
2799TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
2800 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2801
2802 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
2803 ui::Transform injectedEventTransform;
2804 injectedEventTransform.set(matrix);
2805 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
2806 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
2807
2808 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2809 .displayId(ADISPLAY_ID_DEFAULT)
2810 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2811 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2812 .x(untransformedPoint.x)
2813 .y(untransformedPoint.y))
2814 .build();
2815 event.transform(matrix);
2816
2817 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
2818 InputEventInjectionSync::WAIT_FOR_RESULT);
2819
2820 firstWindow->consumeMotionDown();
2821 secondWindow->assertNoEvents();
2822}
2823
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002824TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
2825 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2826
2827 // Send down to the second window.
2828 NotifyMotionArgs downMotionArgs =
2829 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2830 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
2831 mDispatcher->notifyMotion(&downMotionArgs);
2832
2833 firstWindow->assertNoEvents();
2834 const MotionEvent* event = secondWindow->consumeMotion();
2835 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
2836
2837 // Ensure that the events from the "getRaw" API are in logical display coordinates.
2838 EXPECT_EQ(300, event->getRawX(0));
2839 EXPECT_EQ(880, event->getRawY(0));
2840
2841 // Ensure that the x and y values are in the window's coordinate space.
2842 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
2843 // the logical display space. This will be the origin of the window space.
2844 EXPECT_EQ(100, event->getX(0));
2845 EXPECT_EQ(80, event->getY(0));
2846}
2847
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002848using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
2849 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002850
2851class TransferTouchFixture : public InputDispatcherTest,
2852 public ::testing::WithParamInterface<TransferFunction> {};
2853
2854TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07002855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002856
2857 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002858 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002859 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2860 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002861 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002862 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2863 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002864
2865 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002867
2868 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002869 NotifyMotionArgs downMotionArgs =
2870 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2871 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002872 mDispatcher->notifyMotion(&downMotionArgs);
2873 // Only the first window should get the down event
2874 firstWindow->consumeMotionDown();
2875 secondWindow->assertNoEvents();
2876
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002877 // Transfer touch to the second window
2878 TransferFunction f = GetParam();
2879 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2880 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002881 // The first window gets cancel and the second gets down
2882 firstWindow->consumeMotionCancel();
2883 secondWindow->consumeMotionDown();
2884
2885 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002886 NotifyMotionArgs upMotionArgs =
2887 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2888 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002889 mDispatcher->notifyMotion(&upMotionArgs);
2890 // The first window gets no events and the second gets up
2891 firstWindow->assertNoEvents();
2892 secondWindow->consumeMotionUp();
2893}
2894
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002895/**
2896 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
2897 * from. When we have spy windows, there are several windows to choose from: either spy, or the
2898 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
2899 * natural to the user.
2900 * In this test, we are sending a pointer to both spy window and first window. We then try to
2901 * transfer touch to the second window. The dispatcher should identify the first window as the
2902 * one that should lose the gesture, and therefore the action should be to move the gesture from
2903 * the first window to the second.
2904 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
2905 * the other API, as well.
2906 */
2907TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
2908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2909
2910 // Create a couple of windows + a spy window
2911 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002912 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002913 spyWindow->setTrustedOverlay(true);
2914 spyWindow->setSpy(true);
2915 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002916 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002917 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002918 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07002919
2920 // Add the windows to the dispatcher
2921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
2922
2923 // Send down to the first window
2924 NotifyMotionArgs downMotionArgs =
2925 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2926 ADISPLAY_ID_DEFAULT);
2927 mDispatcher->notifyMotion(&downMotionArgs);
2928 // Only the first window and spy should get the down event
2929 spyWindow->consumeMotionDown();
2930 firstWindow->consumeMotionDown();
2931
2932 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
2933 // if f === 'transferTouch'.
2934 TransferFunction f = GetParam();
2935 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2936 ASSERT_TRUE(success);
2937 // The first window gets cancel and the second gets down
2938 firstWindow->consumeMotionCancel();
2939 secondWindow->consumeMotionDown();
2940
2941 // Send up event to the second window
2942 NotifyMotionArgs upMotionArgs =
2943 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2944 ADISPLAY_ID_DEFAULT);
2945 mDispatcher->notifyMotion(&upMotionArgs);
2946 // The first window gets no events and the second+spy get up
2947 firstWindow->assertNoEvents();
2948 spyWindow->consumeMotionUp();
2949 secondWindow->consumeMotionUp();
2950}
2951
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002952TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002954
2955 PointF touchPoint = {10, 10};
2956
2957 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002958 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002959 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2960 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08002961 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002962 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002963 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2964 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08002965 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002966
2967 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002969
2970 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002971 NotifyMotionArgs downMotionArgs =
2972 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2973 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002974 mDispatcher->notifyMotion(&downMotionArgs);
2975 // Only the first window should get the down event
2976 firstWindow->consumeMotionDown();
2977 secondWindow->assertNoEvents();
2978
2979 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002980 NotifyMotionArgs pointerDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002981 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002982 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002983 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2984 // Only the first window should get the pointer down event
2985 firstWindow->consumeMotionPointerDown(1);
2986 secondWindow->assertNoEvents();
2987
2988 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002989 TransferFunction f = GetParam();
2990 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2991 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002992 // The first window gets cancel and the second gets down and pointer down
2993 firstWindow->consumeMotionCancel();
2994 secondWindow->consumeMotionDown();
2995 secondWindow->consumeMotionPointerDown(1);
2996
2997 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002998 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002999 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003000 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003001 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3002 // The first window gets nothing and the second gets pointer up
3003 firstWindow->assertNoEvents();
3004 secondWindow->consumeMotionPointerUp(1);
3005
3006 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003007 NotifyMotionArgs upMotionArgs =
3008 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3009 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003010 mDispatcher->notifyMotion(&upMotionArgs);
3011 // The first window gets nothing and the second gets up
3012 firstWindow->assertNoEvents();
3013 secondWindow->consumeMotionUp();
3014}
3015
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003016// For the cases of single pointer touch and two pointers non-split touch, the api's
3017// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
3018// for the case where there are multiple pointers split across several windows.
3019INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
3020 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003021 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
3022 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003023 return dispatcher->transferTouch(destChannelToken,
3024 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003025 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003026 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
3027 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003028 return dispatcher->transferTouchFocus(from, to,
3029 false /*isDragAndDrop*/);
3030 }));
3031
Svet Ganov5d3bc372020-01-26 23:11:07 -08003032TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07003033 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003034
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003035 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003036 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3037 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003038 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08003039
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003040 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003041 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3042 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003043 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08003044
3045 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00003046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003047
3048 PointF pointInFirst = {300, 200};
3049 PointF pointInSecond = {300, 600};
3050
3051 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003052 NotifyMotionArgs firstDownMotionArgs =
3053 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3054 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003055 mDispatcher->notifyMotion(&firstDownMotionArgs);
3056 // Only the first window should get the down event
3057 firstWindow->consumeMotionDown();
3058 secondWindow->assertNoEvents();
3059
3060 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003061 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003062 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003063 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003064 mDispatcher->notifyMotion(&secondDownMotionArgs);
3065 // The first window gets a move and the second a down
3066 firstWindow->consumeMotionMove();
3067 secondWindow->consumeMotionDown();
3068
3069 // Transfer touch focus to the second window
3070 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
3071 // The first window gets cancel and the new gets pointer down (it already saw down)
3072 firstWindow->consumeMotionCancel();
3073 secondWindow->consumeMotionPointerDown(1);
3074
3075 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003076 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003077 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003078 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003079 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3080 // The first window gets nothing and the second gets pointer up
3081 firstWindow->assertNoEvents();
3082 secondWindow->consumeMotionPointerUp(1);
3083
3084 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003085 NotifyMotionArgs upMotionArgs =
3086 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3087 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003088 mDispatcher->notifyMotion(&upMotionArgs);
3089 // The first window gets nothing and the second gets up
3090 firstWindow->assertNoEvents();
3091 secondWindow->consumeMotionUp();
3092}
3093
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003094// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
3095// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
3096// touch is not supported, so the touch should continue on those windows and the transferred-to
3097// window should get nothing.
3098TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
3099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3100
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003101 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003102 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3103 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003104 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003105
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003106 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003107 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3108 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003109 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003110
3111 // Add the windows to the dispatcher
3112 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
3113
3114 PointF pointInFirst = {300, 200};
3115 PointF pointInSecond = {300, 600};
3116
3117 // Send down to the first window
3118 NotifyMotionArgs firstDownMotionArgs =
3119 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3120 ADISPLAY_ID_DEFAULT, {pointInFirst});
3121 mDispatcher->notifyMotion(&firstDownMotionArgs);
3122 // Only the first window should get the down event
3123 firstWindow->consumeMotionDown();
3124 secondWindow->assertNoEvents();
3125
3126 // Send down to the second window
3127 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003128 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003129 {pointInFirst, pointInSecond});
3130 mDispatcher->notifyMotion(&secondDownMotionArgs);
3131 // The first window gets a move and the second a down
3132 firstWindow->consumeMotionMove();
3133 secondWindow->consumeMotionDown();
3134
3135 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003136 const bool transferred =
3137 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003138 // The 'transferTouch' call should not succeed, because there are 2 touched windows
3139 ASSERT_FALSE(transferred);
3140 firstWindow->assertNoEvents();
3141 secondWindow->assertNoEvents();
3142
3143 // The rest of the dispatch should proceed as normal
3144 // Send pointer up to the second window
3145 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003146 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003147 {pointInFirst, pointInSecond});
3148 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3149 // The first window gets MOVE and the second gets pointer up
3150 firstWindow->consumeMotionMove();
3151 secondWindow->consumeMotionUp();
3152
3153 // Send up event to the first window
3154 NotifyMotionArgs upMotionArgs =
3155 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3156 ADISPLAY_ID_DEFAULT);
3157 mDispatcher->notifyMotion(&upMotionArgs);
3158 // The first window gets nothing and the second gets up
3159 firstWindow->consumeMotionUp();
3160 secondWindow->assertNoEvents();
3161}
3162
Arthur Hungabbb9d82021-09-01 14:52:30 +00003163// This case will create two windows and one mirrored window on the default display and mirror
3164// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
3165// the windows info of second display before default display.
3166TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
3167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3168 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003169 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003170 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003171 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003172 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003173 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003174
3175 sp<FakeWindowHandle> mirrorWindowInPrimary =
3176 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
3177 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003178
3179 sp<FakeWindowHandle> firstWindowInSecondary =
3180 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3181 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003182
3183 sp<FakeWindowHandle> secondWindowInSecondary =
3184 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3185 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003186
3187 // Update window info, let it find window handle of second display first.
3188 mDispatcher->setInputWindows(
3189 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
3190 {ADISPLAY_ID_DEFAULT,
3191 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
3192
3193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3194 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3195 {50, 50}))
3196 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3197
3198 // Window should receive motion event.
3199 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3200
3201 // Transfer touch focus
3202 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
3203 secondWindowInPrimary->getToken()));
3204 // The first window gets cancel.
3205 firstWindowInPrimary->consumeMotionCancel();
3206 secondWindowInPrimary->consumeMotionDown();
3207
3208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3209 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3210 ADISPLAY_ID_DEFAULT, {150, 50}))
3211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3212 firstWindowInPrimary->assertNoEvents();
3213 secondWindowInPrimary->consumeMotionMove();
3214
3215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3216 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3217 {150, 50}))
3218 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3219 firstWindowInPrimary->assertNoEvents();
3220 secondWindowInPrimary->consumeMotionUp();
3221}
3222
3223// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
3224// 'transferTouch' api.
3225TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
3226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3227 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003228 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003229 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003230 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003231 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003232 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003233
3234 sp<FakeWindowHandle> mirrorWindowInPrimary =
3235 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
3236 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003237
3238 sp<FakeWindowHandle> firstWindowInSecondary =
3239 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3240 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003241
3242 sp<FakeWindowHandle> secondWindowInSecondary =
3243 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3244 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003245
3246 // Update window info, let it find window handle of second display first.
3247 mDispatcher->setInputWindows(
3248 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
3249 {ADISPLAY_ID_DEFAULT,
3250 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
3251
3252 // Touch on second display.
3253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3254 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
3255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3256
3257 // Window should receive motion event.
3258 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
3259
3260 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003261 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003262
3263 // The first window gets cancel.
3264 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
3265 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
3266
3267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3268 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3269 SECOND_DISPLAY_ID, {150, 50}))
3270 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3271 firstWindowInPrimary->assertNoEvents();
3272 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
3273
3274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3275 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
3276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3277 firstWindowInPrimary->assertNoEvents();
3278 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
3279}
3280
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003281TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003283 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3284 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003285
Vishnu Nair47074b82020-08-14 11:54:47 -07003286 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003288 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003289
3290 window->consumeFocusEvent(true);
3291
3292 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3293 mDispatcher->notifyKey(&keyArgs);
3294
3295 // Window should receive key down event.
3296 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3297}
3298
3299TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003301 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3302 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003303
Arthur Hung72d8dc32020-03-28 00:48:39 +00003304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003305
3306 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3307 mDispatcher->notifyKey(&keyArgs);
3308 mDispatcher->waitForIdle();
3309
3310 window->assertNoEvents();
3311}
3312
3313// If a window is touchable, but does not have focus, it should receive motion events, but not keys
3314TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07003315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003316 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3317 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003318
Arthur Hung72d8dc32020-03-28 00:48:39 +00003319 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003320
3321 // Send key
3322 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3323 mDispatcher->notifyKey(&keyArgs);
3324 // Send motion
3325 NotifyMotionArgs motionArgs =
3326 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3327 ADISPLAY_ID_DEFAULT);
3328 mDispatcher->notifyMotion(&motionArgs);
3329
3330 // Window should receive only the motion event
3331 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3332 window->assertNoEvents(); // Key event or focus event will not be received
3333}
3334
arthurhungea3f4fc2020-12-21 23:18:53 +08003335TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
3336 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3337
arthurhungea3f4fc2020-12-21 23:18:53 +08003338 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003339 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3340 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08003341 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08003342
arthurhungea3f4fc2020-12-21 23:18:53 +08003343 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003344 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3345 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08003346 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08003347
3348 // Add the windows to the dispatcher
3349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
3350
3351 PointF pointInFirst = {300, 200};
3352 PointF pointInSecond = {300, 600};
3353
3354 // Send down to the first window
3355 NotifyMotionArgs firstDownMotionArgs =
3356 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3357 ADISPLAY_ID_DEFAULT, {pointInFirst});
3358 mDispatcher->notifyMotion(&firstDownMotionArgs);
3359 // Only the first window should get the down event
3360 firstWindow->consumeMotionDown();
3361 secondWindow->assertNoEvents();
3362
3363 // Send down to the second window
3364 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003365 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08003366 {pointInFirst, pointInSecond});
3367 mDispatcher->notifyMotion(&secondDownMotionArgs);
3368 // The first window gets a move and the second a down
3369 firstWindow->consumeMotionMove();
3370 secondWindow->consumeMotionDown();
3371
3372 // Send pointer cancel to the second window
3373 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003374 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08003375 {pointInFirst, pointInSecond});
3376 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
3377 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3378 // The first window gets move and the second gets cancel.
3379 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
3380 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
3381
3382 // Send up event.
3383 NotifyMotionArgs upMotionArgs =
3384 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3385 ADISPLAY_ID_DEFAULT);
3386 mDispatcher->notifyMotion(&upMotionArgs);
3387 // The first window gets up and the second gets nothing.
3388 firstWindow->consumeMotionUp();
3389 secondWindow->assertNoEvents();
3390}
3391
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00003392TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
3393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3394
3395 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003396 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00003397 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3398 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
3399 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
3400 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
3401
3402 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
3403 window->assertNoEvents();
3404 mDispatcher->waitForIdle();
3405}
3406
chaviwd1c23182019-12-20 18:44:56 -08003407class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00003408public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003409 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003410 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07003411 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08003412 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07003413 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00003414 }
3415
chaviwd1c23182019-12-20 18:44:56 -08003416 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
3417
3418 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3419 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
3420 expectedDisplayId, expectedFlags);
3421 }
3422
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003423 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
3424
3425 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
3426
chaviwd1c23182019-12-20 18:44:56 -08003427 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3428 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
3429 expectedDisplayId, expectedFlags);
3430 }
3431
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003432 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3433 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
3434 expectedDisplayId, expectedFlags);
3435 }
3436
chaviwd1c23182019-12-20 18:44:56 -08003437 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3438 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
3439 expectedDisplayId, expectedFlags);
3440 }
3441
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003442 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3443 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3444 expectedDisplayId, expectedFlags);
3445 }
3446
Arthur Hungfbfa5722021-11-16 02:45:54 +00003447 void consumeMotionPointerDown(int32_t pointerIdx) {
3448 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
3449 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3450 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
3451 0 /*expectedFlags*/);
3452 }
3453
Evan Rosky84f07f02021-04-16 10:42:42 -07003454 MotionEvent* consumeMotion() {
3455 InputEvent* event = mInputReceiver->consume();
3456 if (!event) {
3457 ADD_FAILURE() << "No event was produced";
3458 return nullptr;
3459 }
3460 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
3461 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
3462 return nullptr;
3463 }
3464 return static_cast<MotionEvent*>(event);
3465 }
3466
chaviwd1c23182019-12-20 18:44:56 -08003467 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
3468
3469private:
3470 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00003471};
3472
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003473using InputDispatcherMonitorTest = InputDispatcherTest;
3474
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003475/**
3476 * Two entities that receive touch: A window, and a global monitor.
3477 * The touch goes to the window, and then the window disappears.
3478 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
3479 * for the monitor, as well.
3480 * 1. foregroundWindow
3481 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
3482 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003483TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3485 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003486 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003487
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003488 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003489
3490 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3492 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3493 {100, 200}))
3494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3495
3496 // Both the foreground window and the global monitor should receive the touch down
3497 window->consumeMotionDown();
3498 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3499
3500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3501 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3502 ADISPLAY_ID_DEFAULT, {110, 200}))
3503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3504
3505 window->consumeMotionMove();
3506 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
3507
3508 // Now the foreground window goes away
3509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3510 window->consumeMotionCancel();
3511 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
3512
3513 // If more events come in, there will be no more foreground window to send them to. This will
3514 // cause a cancel for the monitor, as well.
3515 ASSERT_EQ(InputEventInjectionResult::FAILED,
3516 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3517 ADISPLAY_ID_DEFAULT, {120, 200}))
3518 << "Injection should fail because the window was removed";
3519 window->assertNoEvents();
3520 // Global monitor now gets the cancel
3521 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3522}
3523
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003524TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07003525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003526 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3527 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00003529
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003530 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00003533 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00003535 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003536 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003537}
3538
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003539TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
3540 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003541
Chris Yea209fde2020-07-22 13:54:51 -07003542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003543 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3544 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003545 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00003546
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00003548 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003549 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08003550 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003551 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003552
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003553 // Pilfer pointers from the monitor.
3554 // This should not do anything and the window should continue to receive events.
3555 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00003556
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003558 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3559 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003561
3562 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
3563 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003564}
3565
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003566TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07003567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003568 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3569 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07003570 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3571 window->setWindowOffset(20, 40);
3572 window->setWindowTransform(0, 1, -1, 0);
3573
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003574 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07003575
3576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3577 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3579 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3580 MotionEvent* event = monitor.consumeMotion();
3581 // Even though window has transform, gesture monitor must not.
3582 ASSERT_EQ(ui::Transform(), event->getTransform());
3583}
3584
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003585TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00003586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003587 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00003588
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003589 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00003590 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003591 << "Injection should fail if there is a monitor, but no touchable window";
3592 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00003593}
3594
chaviw81e2bb92019-12-18 15:03:51 -08003595TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003597 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3598 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08003599
Arthur Hung72d8dc32020-03-28 00:48:39 +00003600 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08003601
3602 NotifyMotionArgs motionArgs =
3603 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3604 ADISPLAY_ID_DEFAULT);
3605
3606 mDispatcher->notifyMotion(&motionArgs);
3607 // Window should receive motion down event.
3608 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3609
3610 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08003611 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08003612 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3613 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
3614 motionArgs.pointerCoords[0].getX() - 10);
3615
3616 mDispatcher->notifyMotion(&motionArgs);
3617 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
3618 0 /*expectedFlags*/);
3619}
3620
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003621/**
3622 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
3623 * the device default right away. In the test scenario, we check both the default value,
3624 * and the action of enabling / disabling.
3625 */
3626TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07003627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003628 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3629 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08003630 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003631
3632 // Set focused application.
3633 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003634 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003635
3636 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00003637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003638 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003639 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3640
3641 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003642 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003643 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003644 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
3645
3646 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003647 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07003648 true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003649 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07003650 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003652 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003653 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
3654
3655 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003656 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003658 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
3659
3660 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003661 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07003662 true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003663 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07003664 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003665 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003666 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003667 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3668
3669 window->assertNoEvents();
3670}
3671
Gang Wange9087892020-01-07 12:17:14 -05003672TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3675 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05003676
3677 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003678 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05003679
Arthur Hung72d8dc32020-03-28 00:48:39 +00003680 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003681 setFocusedWindow(window);
3682
Gang Wange9087892020-01-07 12:17:14 -05003683 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3684
3685 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3686 mDispatcher->notifyKey(&keyArgs);
3687
3688 InputEvent* event = window->consume();
3689 ASSERT_NE(event, nullptr);
3690
3691 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3692 ASSERT_NE(verified, nullptr);
3693 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
3694
3695 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
3696 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
3697 ASSERT_EQ(keyArgs.source, verified->source);
3698 ASSERT_EQ(keyArgs.displayId, verified->displayId);
3699
3700 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
3701
3702 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05003703 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003704 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05003705 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
3706 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
3707 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
3708 ASSERT_EQ(0, verifiedKey.repeatCount);
3709}
3710
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003711TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3714 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003715
3716 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3717
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003718 ui::Transform transform;
3719 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3720
3721 gui::DisplayInfo displayInfo;
3722 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
3723 displayInfo.transform = transform;
3724
3725 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003726
3727 NotifyMotionArgs motionArgs =
3728 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3729 ADISPLAY_ID_DEFAULT);
3730 mDispatcher->notifyMotion(&motionArgs);
3731
3732 InputEvent* event = window->consume();
3733 ASSERT_NE(event, nullptr);
3734
3735 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3736 ASSERT_NE(verified, nullptr);
3737 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
3738
3739 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
3740 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
3741 EXPECT_EQ(motionArgs.source, verified->source);
3742 EXPECT_EQ(motionArgs.displayId, verified->displayId);
3743
3744 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
3745
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003746 const vec2 rawXY =
3747 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
3748 motionArgs.pointerCoords[0].getXYValue());
3749 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
3750 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003751 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003752 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003753 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003754 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
3755 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
3756}
3757
chaviw09c8d2d2020-08-24 15:48:26 -07003758/**
3759 * Ensure that separate calls to sign the same data are generating the same key.
3760 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
3761 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
3762 * tests.
3763 */
3764TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
3765 KeyEvent event = getTestKeyEvent();
3766 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3767
3768 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
3769 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
3770 ASSERT_EQ(hmac1, hmac2);
3771}
3772
3773/**
3774 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
3775 */
3776TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
3777 KeyEvent event = getTestKeyEvent();
3778 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3779 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
3780
3781 verifiedEvent.deviceId += 1;
3782 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3783
3784 verifiedEvent.source += 1;
3785 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3786
3787 verifiedEvent.eventTimeNanos += 1;
3788 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3789
3790 verifiedEvent.displayId += 1;
3791 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3792
3793 verifiedEvent.action += 1;
3794 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3795
3796 verifiedEvent.downTimeNanos += 1;
3797 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3798
3799 verifiedEvent.flags += 1;
3800 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3801
3802 verifiedEvent.keyCode += 1;
3803 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3804
3805 verifiedEvent.scanCode += 1;
3806 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3807
3808 verifiedEvent.metaState += 1;
3809 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3810
3811 verifiedEvent.repeatCount += 1;
3812 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3813}
3814
Vishnu Nair958da932020-08-21 17:12:37 -07003815TEST_F(InputDispatcherTest, SetFocusedWindow) {
3816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3817 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003818 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003819 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003820 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003821 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3822
3823 // Top window is also focusable but is not granted focus.
3824 windowTop->setFocusable(true);
3825 windowSecond->setFocusable(true);
3826 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3827 setFocusedWindow(windowSecond);
3828
3829 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3831 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003832
3833 // Focused window should receive event.
3834 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3835 windowTop->assertNoEvents();
3836}
3837
3838TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
3839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3840 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003841 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003842 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3843
3844 window->setFocusable(true);
3845 // Release channel for window is no longer valid.
3846 window->releaseChannel();
3847 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3848 setFocusedWindow(window);
3849
3850 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003851 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3852 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003853
3854 // window channel is invalid, so it should not receive any input event.
3855 window->assertNoEvents();
3856}
3857
3858TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
3859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3860 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003861 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003862 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07003863 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3864
Vishnu Nair958da932020-08-21 17:12:37 -07003865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3866 setFocusedWindow(window);
3867
3868 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003869 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3870 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003871
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003872 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07003873 window->assertNoEvents();
3874}
3875
3876TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3878 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003879 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003880 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003881 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003882 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3883
3884 windowTop->setFocusable(true);
3885 windowSecond->setFocusable(true);
3886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3887 setFocusedWindow(windowTop);
3888 windowTop->consumeFocusEvent(true);
3889
3890 setFocusedWindow(windowSecond, windowTop);
3891 windowSecond->consumeFocusEvent(true);
3892 windowTop->consumeFocusEvent(false);
3893
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3895 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003896
3897 // Focused window should receive event.
3898 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3899}
3900
3901TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3903 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003904 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003905 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003906 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003907 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3908
3909 windowTop->setFocusable(true);
3910 windowSecond->setFocusable(true);
3911 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3912 setFocusedWindow(windowSecond, windowTop);
3913
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003914 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3915 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003916
3917 // Event should be dropped.
3918 windowTop->assertNoEvents();
3919 windowSecond->assertNoEvents();
3920}
3921
3922TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3924 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003925 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003926 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003927 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
3928 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07003929 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3930
3931 window->setFocusable(true);
3932 previousFocusedWindow->setFocusable(true);
3933 window->setVisible(false);
3934 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3935 setFocusedWindow(previousFocusedWindow);
3936 previousFocusedWindow->consumeFocusEvent(true);
3937
3938 // Requesting focus on invisible window takes focus from currently focused window.
3939 setFocusedWindow(window);
3940 previousFocusedWindow->consumeFocusEvent(false);
3941
3942 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003944 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003945 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003946
3947 // Window does not get focus event or key down.
3948 window->assertNoEvents();
3949
3950 // Window becomes visible.
3951 window->setVisible(true);
3952 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3953
3954 // Window receives focus event.
3955 window->consumeFocusEvent(true);
3956 // Focused window receives key down.
3957 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3958}
3959
Vishnu Nair599f1412021-06-21 10:39:58 -07003960TEST_F(InputDispatcherTest, DisplayRemoved) {
3961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3962 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003963 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07003964 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3965
3966 // window is granted focus.
3967 window->setFocusable(true);
3968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3969 setFocusedWindow(window);
3970 window->consumeFocusEvent(true);
3971
3972 // When a display is removed window loses focus.
3973 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3974 window->consumeFocusEvent(false);
3975}
3976
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003977/**
3978 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3979 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3980 * of the 'slipperyEnterWindow'.
3981 *
3982 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3983 * a way so that the touched location is no longer covered by the top window.
3984 *
3985 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3986 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3987 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3988 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3989 * with ACTION_DOWN).
3990 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3991 * window moved itself away from the touched location and had Flag::SLIPPERY.
3992 *
3993 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3994 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3995 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3996 *
3997 * In this test, we ensure that the event received by the bottom window has
3998 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3999 */
4000TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00004001 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
4002 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004003
4004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4005 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4006
4007 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004008 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004009 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004010 // Make sure this one overlaps the bottom window
4011 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
4012 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
4013 // one. Windows with the same owner are not considered to be occluding each other.
4014 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
4015
4016 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004017 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004018 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
4019
4020 mDispatcher->setInputWindows(
4021 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
4022
4023 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
4024 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4025 ADISPLAY_ID_DEFAULT, {{50, 50}});
4026 mDispatcher->notifyMotion(&args);
4027 slipperyExitWindow->consumeMotionDown();
4028 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
4029 mDispatcher->setInputWindows(
4030 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
4031
4032 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4033 ADISPLAY_ID_DEFAULT, {{51, 51}});
4034 mDispatcher->notifyMotion(&args);
4035
4036 slipperyExitWindow->consumeMotionCancel();
4037
4038 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
4039 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
4040}
4041
Garfield Tan1c7bc862020-01-28 13:24:04 -08004042class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
4043protected:
4044 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
4045 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
4046
Chris Yea209fde2020-07-22 13:54:51 -07004047 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004048 sp<FakeWindowHandle> mWindow;
4049
4050 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004051 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08004052 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004053 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004054 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
4055 ASSERT_EQ(OK, mDispatcher->start());
4056
4057 setUpWindow();
4058 }
4059
4060 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07004061 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004062 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004063
Vishnu Nair47074b82020-08-14 11:54:47 -07004064 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004065 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004066 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004067 mWindow->consumeFocusEvent(true);
4068 }
4069
Chris Ye2ad95392020-09-01 13:44:44 -07004070 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08004071 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07004072 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004073 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
4074 mDispatcher->notifyKey(&keyArgs);
4075
4076 // Window should receive key down event.
4077 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4078 }
4079
4080 void expectKeyRepeatOnce(int32_t repeatCount) {
4081 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
4082 InputEvent* repeatEvent = mWindow->consume();
4083 ASSERT_NE(nullptr, repeatEvent);
4084
4085 uint32_t eventType = repeatEvent->getType();
4086 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
4087
4088 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
4089 uint32_t eventAction = repeatKeyEvent->getAction();
4090 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
4091 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
4092 }
4093
Chris Ye2ad95392020-09-01 13:44:44 -07004094 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08004095 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07004096 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004097 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
4098 mDispatcher->notifyKey(&keyArgs);
4099
4100 // Window should receive key down event.
4101 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
4102 0 /*expectedFlags*/);
4103 }
4104};
4105
4106TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07004107 sendAndConsumeKeyDown(1 /* deviceId */);
4108 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4109 expectKeyRepeatOnce(repeatCount);
4110 }
4111}
4112
4113TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
4114 sendAndConsumeKeyDown(1 /* deviceId */);
4115 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4116 expectKeyRepeatOnce(repeatCount);
4117 }
4118 sendAndConsumeKeyDown(2 /* deviceId */);
4119 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08004120 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4121 expectKeyRepeatOnce(repeatCount);
4122 }
4123}
4124
4125TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07004126 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004127 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07004128 sendAndConsumeKeyUp(1 /* deviceId */);
4129 mWindow->assertNoEvents();
4130}
4131
4132TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
4133 sendAndConsumeKeyDown(1 /* deviceId */);
4134 expectKeyRepeatOnce(1 /*repeatCount*/);
4135 sendAndConsumeKeyDown(2 /* deviceId */);
4136 expectKeyRepeatOnce(1 /*repeatCount*/);
4137 // Stale key up from device 1.
4138 sendAndConsumeKeyUp(1 /* deviceId */);
4139 // Device 2 is still down, keep repeating
4140 expectKeyRepeatOnce(2 /*repeatCount*/);
4141 expectKeyRepeatOnce(3 /*repeatCount*/);
4142 // Device 2 key up
4143 sendAndConsumeKeyUp(2 /* deviceId */);
4144 mWindow->assertNoEvents();
4145}
4146
4147TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
4148 sendAndConsumeKeyDown(1 /* deviceId */);
4149 expectKeyRepeatOnce(1 /*repeatCount*/);
4150 sendAndConsumeKeyDown(2 /* deviceId */);
4151 expectKeyRepeatOnce(1 /*repeatCount*/);
4152 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
4153 sendAndConsumeKeyUp(2 /* deviceId */);
4154 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08004155 mWindow->assertNoEvents();
4156}
4157
liushenxiang42232912021-05-21 20:24:09 +08004158TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
4159 sendAndConsumeKeyDown(DEVICE_ID);
4160 expectKeyRepeatOnce(1 /*repeatCount*/);
4161 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
4162 mDispatcher->notifyDeviceReset(&args);
4163 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
4164 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
4165 mWindow->assertNoEvents();
4166}
4167
Garfield Tan1c7bc862020-01-28 13:24:04 -08004168TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07004169 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004170 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4171 InputEvent* repeatEvent = mWindow->consume();
4172 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
4173 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
4174 IdGenerator::getSource(repeatEvent->getId()));
4175 }
4176}
4177
4178TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07004179 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004180
4181 std::unordered_set<int32_t> idSet;
4182 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4183 InputEvent* repeatEvent = mWindow->consume();
4184 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
4185 int32_t id = repeatEvent->getId();
4186 EXPECT_EQ(idSet.end(), idSet.find(id));
4187 idSet.insert(id);
4188 }
4189}
4190
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004191/* Test InputDispatcher for MultiDisplay */
4192class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
4193public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004194 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004195 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08004196
Chris Yea209fde2020-07-22 13:54:51 -07004197 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004198 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004199 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004200
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004201 // Set focus window for primary display, but focused display would be second one.
4202 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07004203 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004204 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004205 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004206 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08004207
Chris Yea209fde2020-07-22 13:54:51 -07004208 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004209 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004210 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004211 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004212 // Set focus display to second one.
4213 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
4214 // Set focus window for second display.
4215 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07004216 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004217 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004218 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004219 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004220 }
4221
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004222 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004223 InputDispatcherTest::TearDown();
4224
Chris Yea209fde2020-07-22 13:54:51 -07004225 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004226 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07004227 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004228 windowInSecondary.clear();
4229 }
4230
4231protected:
Chris Yea209fde2020-07-22 13:54:51 -07004232 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004233 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07004234 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004235 sp<FakeWindowHandle> windowInSecondary;
4236};
4237
4238TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
4239 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4241 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4242 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004243 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08004244 windowInSecondary->assertNoEvents();
4245
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004246 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4248 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08004250 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004251 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08004252}
4253
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004254TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08004255 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4257 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004258 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004259 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08004260 windowInSecondary->assertNoEvents();
4261
4262 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004264 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08004265 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004266 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08004267
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004268 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004269 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08004270
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004271 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004272 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
4273 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08004274
4275 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004276 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004277 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08004278 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004279 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08004280 windowInSecondary->assertNoEvents();
4281}
4282
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004283// Test per-display input monitors for motion event.
4284TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08004285 FakeMonitorReceiver monitorInPrimary =
4286 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4287 FakeMonitorReceiver monitorInSecondary =
4288 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004289
4290 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4292 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004294 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004295 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004296 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004297 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004298
4299 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4301 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004303 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004304 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004305 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08004306 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004307
4308 // Test inject a non-pointer motion event.
4309 // If specific a display, it will dispatch to the focused window of particular display,
4310 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4312 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
4313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004314 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004315 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004316 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08004317 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004318}
4319
4320// Test per-display input monitors for key event.
4321TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004322 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08004323 FakeMonitorReceiver monitorInPrimary =
4324 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4325 FakeMonitorReceiver monitorInSecondary =
4326 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004327
4328 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4330 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004331 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004332 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004333 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08004334 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004335}
4336
Vishnu Nair958da932020-08-21 17:12:37 -07004337TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
4338 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004339 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004340 secondWindowInPrimary->setFocusable(true);
4341 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
4342 setFocusedWindow(secondWindowInPrimary);
4343 windowInPrimary->consumeFocusEvent(false);
4344 secondWindowInPrimary->consumeFocusEvent(true);
4345
4346 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
4348 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004349 windowInPrimary->assertNoEvents();
4350 windowInSecondary->assertNoEvents();
4351 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4352}
4353
Arthur Hungdfd528e2021-12-08 13:23:04 +00004354TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
4355 FakeMonitorReceiver monitorInPrimary =
4356 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4357 FakeMonitorReceiver monitorInSecondary =
4358 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
4359
4360 // Test touch down on primary display.
4361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4362 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4364 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4365 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4366
4367 // Test touch down on second display.
4368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4369 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4371 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
4372 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
4373
4374 // Trigger cancel touch.
4375 mDispatcher->cancelCurrentTouch();
4376 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4377 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4378 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
4379 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
4380
4381 // Test inject a move motion event, no window/monitor should receive the event.
4382 ASSERT_EQ(InputEventInjectionResult::FAILED,
4383 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4384 ADISPLAY_ID_DEFAULT, {110, 200}))
4385 << "Inject motion event should return InputEventInjectionResult::FAILED";
4386 windowInPrimary->assertNoEvents();
4387 monitorInPrimary.assertNoEvents();
4388
4389 ASSERT_EQ(InputEventInjectionResult::FAILED,
4390 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4391 SECOND_DISPLAY_ID, {110, 200}))
4392 << "Inject motion event should return InputEventInjectionResult::FAILED";
4393 windowInSecondary->assertNoEvents();
4394 monitorInSecondary.assertNoEvents();
4395}
4396
Jackal Guof9696682018-10-05 12:23:23 +08004397class InputFilterTest : public InputDispatcherTest {
4398protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004399 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
4400 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08004401 NotifyMotionArgs motionArgs;
4402
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004403 motionArgs =
4404 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08004405 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004406 motionArgs =
4407 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08004408 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004409 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08004410 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004411 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
4412 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08004413 } else {
4414 mFakePolicy->assertFilterInputEventWasNotCalled();
4415 }
4416 }
4417
4418 void testNotifyKey(bool expectToBeFiltered) {
4419 NotifyKeyArgs keyArgs;
4420
4421 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
4422 mDispatcher->notifyKey(&keyArgs);
4423 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
4424 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004425 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08004426
4427 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08004428 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08004429 } else {
4430 mFakePolicy->assertFilterInputEventWasNotCalled();
4431 }
4432 }
4433};
4434
4435// Test InputFilter for MotionEvent
4436TEST_F(InputFilterTest, MotionEvent_InputFilter) {
4437 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
4438 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
4439 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
4440
4441 // Enable InputFilter
4442 mDispatcher->setInputFilterEnabled(true);
4443 // Test touch on both primary and second display, and check if both events are filtered.
4444 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
4445 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
4446
4447 // Disable InputFilter
4448 mDispatcher->setInputFilterEnabled(false);
4449 // Test touch on both primary and second display, and check if both events aren't filtered.
4450 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
4451 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
4452}
4453
4454// Test InputFilter for KeyEvent
4455TEST_F(InputFilterTest, KeyEvent_InputFilter) {
4456 // Since the InputFilter is disabled by default, check if key event aren't filtered.
4457 testNotifyKey(/*expectToBeFiltered*/ false);
4458
4459 // Enable InputFilter
4460 mDispatcher->setInputFilterEnabled(true);
4461 // Send a key event, and check if it is filtered.
4462 testNotifyKey(/*expectToBeFiltered*/ true);
4463
4464 // Disable InputFilter
4465 mDispatcher->setInputFilterEnabled(false);
4466 // Send a key event, and check if it isn't filtered.
4467 testNotifyKey(/*expectToBeFiltered*/ false);
4468}
4469
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004470// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
4471// logical display coordinate space.
4472TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
4473 ui::Transform firstDisplayTransform;
4474 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
4475 ui::Transform secondDisplayTransform;
4476 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
4477
4478 std::vector<gui::DisplayInfo> displayInfos(2);
4479 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
4480 displayInfos[0].transform = firstDisplayTransform;
4481 displayInfos[1].displayId = SECOND_DISPLAY_ID;
4482 displayInfos[1].transform = secondDisplayTransform;
4483
4484 mDispatcher->onWindowInfosChanged({}, displayInfos);
4485
4486 // Enable InputFilter
4487 mDispatcher->setInputFilterEnabled(true);
4488
4489 // Ensure the correct transforms are used for the displays.
4490 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
4491 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
4492}
4493
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004494class InputFilterInjectionPolicyTest : public InputDispatcherTest {
4495protected:
4496 virtual void SetUp() override {
4497 InputDispatcherTest::SetUp();
4498
4499 /**
4500 * We don't need to enable input filter to test the injected event policy, but we enabled it
4501 * here to make the tests more realistic, since this policy only matters when inputfilter is
4502 * on.
4503 */
4504 mDispatcher->setInputFilterEnabled(true);
4505
4506 std::shared_ptr<InputApplicationHandle> application =
4507 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004508 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
4509 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004510
4511 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4512 mWindow->setFocusable(true);
4513 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4514 setFocusedWindow(mWindow);
4515 mWindow->consumeFocusEvent(true);
4516 }
4517
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004518 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
4519 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004520 KeyEvent event;
4521
4522 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4523 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
4524 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
4525 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
4526 const int32_t additionalPolicyFlags =
4527 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
4528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan5735a322022-04-11 17:23:34 +00004529 mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004530 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
4531 policyFlags | additionalPolicyFlags));
4532
4533 InputEvent* received = mWindow->consume();
4534 ASSERT_NE(nullptr, received);
4535 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004536 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
4537 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
4538 ASSERT_EQ(flags, keyEvent.getFlags());
4539 }
4540
4541 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
4542 int32_t flags) {
4543 MotionEvent event;
4544 PointerProperties pointerProperties[1];
4545 PointerCoords pointerCoords[1];
4546 pointerProperties[0].clear();
4547 pointerProperties[0].id = 0;
4548 pointerCoords[0].clear();
4549 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
4550 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
4551
4552 ui::Transform identityTransform;
4553 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4554 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
4555 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
4556 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
4557 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07004558 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07004559 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004560 /*pointerCount*/ 1, pointerProperties, pointerCoords);
4561
4562 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
4563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan5735a322022-04-11 17:23:34 +00004564 mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004565 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
4566 policyFlags | additionalPolicyFlags));
4567
4568 InputEvent* received = mWindow->consume();
4569 ASSERT_NE(nullptr, received);
4570 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
4571 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
4572 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
4573 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004574 }
4575
4576private:
4577 sp<FakeWindowHandle> mWindow;
4578};
4579
4580TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004581 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
4582 // filter. Without it, the event will no different from a regularly injected event, and the
4583 // injected device id will be overwritten.
4584 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4585 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004586}
4587
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004588TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004589 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004590 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4591 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4592}
4593
4594TEST_F(InputFilterInjectionPolicyTest,
4595 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
4596 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
4597 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4598 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004599}
4600
4601TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
4602 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004603 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004604}
4605
chaviwfd6d3512019-03-25 13:23:49 -07004606class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004607 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07004608 InputDispatcherTest::SetUp();
4609
Chris Yea209fde2020-07-22 13:54:51 -07004610 std::shared_ptr<FakeApplicationHandle> application =
4611 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004612 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004613 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004614 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07004615
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004616 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004617 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004618 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07004619
4620 // Set focused application.
4621 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004622 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07004623
4624 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004626 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004627 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07004628 }
4629
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004630 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07004631 InputDispatcherTest::TearDown();
4632
4633 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004634 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07004635 }
4636
4637protected:
4638 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004639 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004640 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07004641};
4642
4643// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4644// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
4645// the onPointerDownOutsideFocus callback.
4646TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004648 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4649 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004651 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004652
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004653 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07004654 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
4655}
4656
4657// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
4658// DOWN on the window that doesn't have focus. Ensure no window received the
4659// onPointerDownOutsideFocus callback.
4660TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004662 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004664 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004665
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004666 ASSERT_TRUE(mDispatcher->waitForIdle());
4667 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004668}
4669
4670// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
4671// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
4672TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4674 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004675 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004676 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004677
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004678 ASSERT_TRUE(mDispatcher->waitForIdle());
4679 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004680}
4681
4682// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4683// DOWN on the window that already has focus. Ensure no window received the
4684// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004685TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004687 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004688 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004689 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004690 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004691
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004692 ASSERT_TRUE(mDispatcher->waitForIdle());
4693 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004694}
4695
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08004696// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
4697// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
4698TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
4699 const MotionEvent event =
4700 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4701 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
4702 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
4703 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
4704 .build();
4705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
4706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4707 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
4708
4709 ASSERT_TRUE(mDispatcher->waitForIdle());
4710 mFakePolicy->assertOnPointerDownWasNotCalled();
4711 // Ensure that the unfocused window did not receive any FOCUS events.
4712 mUnfocusedWindow->assertNoEvents();
4713}
4714
chaviwaf87b3e2019-10-01 16:59:28 -07004715// These tests ensures we can send touch events to a single client when there are multiple input
4716// windows that point to the same client token.
4717class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
4718 virtual void SetUp() override {
4719 InputDispatcherTest::SetUp();
4720
Chris Yea209fde2020-07-22 13:54:51 -07004721 std::shared_ptr<FakeApplicationHandle> application =
4722 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004723 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
4724 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07004725 mWindow1->setFrame(Rect(0, 0, 100, 100));
4726
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004727 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
4728 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07004729 mWindow2->setFrame(Rect(100, 100, 200, 200));
4730
Arthur Hung72d8dc32020-03-28 00:48:39 +00004731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07004732 }
4733
4734protected:
4735 sp<FakeWindowHandle> mWindow1;
4736 sp<FakeWindowHandle> mWindow2;
4737
4738 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05004739 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07004740 vec2 vals = windowInfo->transform.transform(point.x, point.y);
4741 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07004742 }
4743
4744 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
4745 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004746 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07004747 InputEvent* event = window->consume();
4748
4749 ASSERT_NE(nullptr, event) << name.c_str()
4750 << ": consumer should have returned non-NULL event.";
4751
4752 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
4753 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
4754 << " event, got " << inputEventTypeToString(event->getType()) << " event";
4755
4756 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004757 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08004758 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07004759
4760 for (size_t i = 0; i < points.size(); i++) {
4761 float expectedX = points[i].x;
4762 float expectedY = points[i].y;
4763
4764 EXPECT_EQ(expectedX, motionEvent.getX(i))
4765 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
4766 << ", got " << motionEvent.getX(i);
4767 EXPECT_EQ(expectedY, motionEvent.getY(i))
4768 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
4769 << ", got " << motionEvent.getY(i);
4770 }
4771 }
chaviw9eaa22c2020-07-01 16:21:27 -07004772
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004773 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07004774 std::vector<PointF> expectedPoints) {
4775 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
4776 ADISPLAY_ID_DEFAULT, touchedPoints);
4777 mDispatcher->notifyMotion(&motionArgs);
4778
4779 // Always consume from window1 since it's the window that has the InputReceiver
4780 consumeMotionEvent(mWindow1, action, expectedPoints);
4781 }
chaviwaf87b3e2019-10-01 16:59:28 -07004782};
4783
4784TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
4785 // Touch Window 1
4786 PointF touchedPoint = {10, 10};
4787 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004788 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004789
4790 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004791 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004792
4793 // Touch Window 2
4794 touchedPoint = {150, 150};
4795 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004796 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004797}
4798
chaviw9eaa22c2020-07-01 16:21:27 -07004799TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
4800 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07004801 mWindow2->setWindowScale(0.5f, 0.5f);
4802
4803 // Touch Window 1
4804 PointF touchedPoint = {10, 10};
4805 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004806 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004807 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004808 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004809
4810 // Touch Window 2
4811 touchedPoint = {150, 150};
4812 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004813 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
4814 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004815
chaviw9eaa22c2020-07-01 16:21:27 -07004816 // Update the transform so rotation is set
4817 mWindow2->setWindowTransform(0, -1, 1, 0);
4818 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
4819 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004820}
4821
chaviw9eaa22c2020-07-01 16:21:27 -07004822TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004823 mWindow2->setWindowScale(0.5f, 0.5f);
4824
4825 // Touch Window 1
4826 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4827 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004828 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004829
4830 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07004831 touchedPoints.push_back(PointF{150, 150});
4832 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004833 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004834
chaviw9eaa22c2020-07-01 16:21:27 -07004835 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004836 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07004837 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004838
chaviw9eaa22c2020-07-01 16:21:27 -07004839 // Update the transform so rotation is set for Window 2
4840 mWindow2->setWindowTransform(0, -1, 1, 0);
4841 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004842 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004843}
4844
chaviw9eaa22c2020-07-01 16:21:27 -07004845TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004846 mWindow2->setWindowScale(0.5f, 0.5f);
4847
4848 // Touch Window 1
4849 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4850 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004851 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004852
4853 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07004854 touchedPoints.push_back(PointF{150, 150});
4855 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004856
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004857 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004858
4859 // Move both windows
4860 touchedPoints = {{20, 20}, {175, 175}};
4861 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4862 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4863
chaviw9eaa22c2020-07-01 16:21:27 -07004864 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004865
chaviw9eaa22c2020-07-01 16:21:27 -07004866 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004867 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07004868 expectedPoints.pop_back();
4869
4870 // Touch Window 2
4871 mWindow2->setWindowTransform(0, -1, 1, 0);
4872 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004873 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07004874
4875 // Move both windows
4876 touchedPoints = {{20, 20}, {175, 175}};
4877 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4878 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4879
4880 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004881}
4882
4883TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
4884 mWindow1->setWindowScale(0.5f, 0.5f);
4885
4886 // Touch Window 1
4887 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4888 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004889 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004890
4891 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07004892 touchedPoints.push_back(PointF{150, 150});
4893 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004894
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004895 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004896
4897 // Move both windows
4898 touchedPoints = {{20, 20}, {175, 175}};
4899 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4900 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4901
chaviw9eaa22c2020-07-01 16:21:27 -07004902 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004903}
4904
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004905class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
4906 virtual void SetUp() override {
4907 InputDispatcherTest::SetUp();
4908
Chris Yea209fde2020-07-22 13:54:51 -07004909 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004910 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004911 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
4912 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004913 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004914 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004915 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004916
4917 // Set focused application.
4918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4919
4920 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004921 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004922 mWindow->consumeFocusEvent(true);
4923 }
4924
4925 virtual void TearDown() override {
4926 InputDispatcherTest::TearDown();
4927 mWindow.clear();
4928 }
4929
4930protected:
Chris Yea209fde2020-07-22 13:54:51 -07004931 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004932 sp<FakeWindowHandle> mWindow;
4933 static constexpr PointF WINDOW_LOCATION = {20, 20};
4934
4935 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004937 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4938 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004940 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4941 WINDOW_LOCATION));
4942 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004943
4944 sp<FakeWindowHandle> addSpyWindow() {
4945 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004946 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004947 spy->setTrustedOverlay(true);
4948 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08004949 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004950 spy->setDispatchingTimeout(30ms);
4951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
4952 return spy;
4953 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004954};
4955
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004956// Send a tap and respond, which should not cause an ANR.
4957TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4958 tapOnWindow();
4959 mWindow->consumeMotionDown();
4960 mWindow->consumeMotionUp();
4961 ASSERT_TRUE(mDispatcher->waitForIdle());
4962 mFakePolicy->assertNotifyAnrWasNotCalled();
4963}
4964
4965// Send a regular key and respond, which should not cause an ANR.
4966TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004968 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4969 ASSERT_TRUE(mDispatcher->waitForIdle());
4970 mFakePolicy->assertNotifyAnrWasNotCalled();
4971}
4972
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004973TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4974 mWindow->setFocusable(false);
4975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4976 mWindow->consumeFocusEvent(false);
4977
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004978 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004979 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004980 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4981 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004983 // Key will not go to window because we have no focused window.
4984 // The 'no focused window' ANR timer should start instead.
4985
4986 // Now, the focused application goes away.
4987 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4988 // The key should get dropped and there should be no ANR.
4989
4990 ASSERT_TRUE(mDispatcher->waitForIdle());
4991 mFakePolicy->assertNotifyAnrWasNotCalled();
4992}
4993
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004994// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004995// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4996// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004997TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5000 WINDOW_LOCATION));
5001
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005002 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
5003 ASSERT_TRUE(sequenceNum);
5004 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005005 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005006
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005007 mWindow->finishEvent(*sequenceNum);
5008 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
5009 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005010 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005011 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005012}
5013
5014// Send a key to the app and have the app not respond right away.
5015TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
5016 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005018 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
5019 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005020 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005021 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005022 ASSERT_TRUE(mDispatcher->waitForIdle());
5023}
5024
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005025// We have a focused application, but no focused window
5026TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005027 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5029 mWindow->consumeFocusEvent(false);
5030
5031 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005033 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5034 WINDOW_LOCATION));
5035 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
5036 mDispatcher->waitForIdle();
5037 mFakePolicy->assertNotifyAnrWasNotCalled();
5038
5039 // Once a focused event arrives, we get an ANR for this application
5040 // We specify the injection timeout to be smaller than the application timeout, to ensure that
5041 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005042 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005043 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005044 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005045 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005046 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07005047 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005048 ASSERT_TRUE(mDispatcher->waitForIdle());
5049}
5050
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08005051/**
5052 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
5053 * there will not be an ANR.
5054 */
5055TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
5056 mWindow->setFocusable(false);
5057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5058 mWindow->consumeFocusEvent(false);
5059
5060 KeyEvent event;
5061 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
5062 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
5063
5064 // Define a valid key down event that is stale (too old).
5065 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
5066 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
5067 AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime);
5068
5069 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
5070
5071 InputEventInjectionResult result =
Prabir Pradhan5735a322022-04-11 17:23:34 +00005072 mDispatcher->injectInputEvent(&event, {} /* targetUid */,
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08005073 InputEventInjectionSync::WAIT_FOR_RESULT,
5074 INJECT_EVENT_TIMEOUT, policyFlags);
5075 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
5076 << "Injection should fail because the event is stale";
5077
5078 ASSERT_TRUE(mDispatcher->waitForIdle());
5079 mFakePolicy->assertNotifyAnrWasNotCalled();
5080 mWindow->assertNoEvents();
5081}
5082
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005083// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005084// Make sure that we don't notify policy twice about the same ANR.
5085TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005086 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5088 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005089
5090 // Once a focused event arrives, we get an ANR for this application
5091 // We specify the injection timeout to be smaller than the application timeout, to ensure that
5092 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005093 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005094 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005095 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005096 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07005097 const std::chrono::duration appTimeout =
5098 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
5099 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005100
Vishnu Naire4df8752022-09-08 09:17:55 -07005101 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005102 // ANR should not be raised again. It is up to policy to do that if it desires.
5103 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005104
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005105 // If we now get a focused window, the ANR should stop, but the policy handles that via
5106 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005107 ASSERT_TRUE(mDispatcher->waitForIdle());
5108}
5109
5110// We have a focused application, but no focused window
5111TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005112 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5114 mWindow->consumeFocusEvent(false);
5115
5116 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005117 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005118 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005119 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
5120 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005121
Vishnu Naire4df8752022-09-08 09:17:55 -07005122 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
5123 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005124
5125 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005126 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005127 ASSERT_TRUE(mDispatcher->waitForIdle());
5128 mWindow->assertNoEvents();
5129}
5130
5131/**
5132 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
5133 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
5134 * If we process 1 of the events, but ANR on the second event with the same timestamp,
5135 * the ANR mechanism should still work.
5136 *
5137 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
5138 * DOWN event, while not responding on the second one.
5139 */
5140TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
5141 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
5142 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5143 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
5144 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
5145 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005146 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005147
5148 // Now send ACTION_UP, with identical timestamp
5149 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5150 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
5151 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
5152 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005153 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005154
5155 // We have now sent down and up. Let's consume first event and then ANR on the second.
5156 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5157 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005158 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005159}
5160
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005161// A spy window can receive an ANR
5162TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
5163 sp<FakeWindowHandle> spy = addSpyWindow();
5164
5165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5166 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5167 WINDOW_LOCATION));
5168 mWindow->consumeMotionDown();
5169
5170 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
5171 ASSERT_TRUE(sequenceNum);
5172 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005173 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005174
5175 spy->finishEvent(*sequenceNum);
5176 spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
5177 0 /*flags*/);
5178 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005179 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005180}
5181
5182// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005183// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005184TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
5185 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005186
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5188 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005189 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005191
5192 // Stuck on the ACTION_UP
5193 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005194 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005195
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005196 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005197 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005198 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5199 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005200
5201 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
5202 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005203 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005204 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005205 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005206}
5207
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005208// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005209// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005210TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
5211 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005212
5213 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005214 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5215 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005216
5217 mWindow->consumeMotionDown();
5218 // Stuck on the ACTION_UP
5219 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005220 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005221
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005222 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005223 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005224 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5225 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005226
5227 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
5228 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005229 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005230 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005231 spy->assertNoEvents();
5232}
5233
5234TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
5235 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
5236
5237 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5238
5239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5240 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5241 WINDOW_LOCATION));
5242
5243 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5244 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
5245 ASSERT_TRUE(consumeSeq);
5246
Prabir Pradhanedd96402022-02-15 01:46:16 -08005247 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005248
5249 monitor.finishEvent(*consumeSeq);
5250 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5251
5252 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005253 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005254}
5255
5256// If a window is unresponsive, then you get anr. if the window later catches up and starts to
5257// process events, you don't get an anr. When the window later becomes unresponsive again, you
5258// get an ANR again.
5259// 1. tap -> block on ACTION_UP -> receive ANR
5260// 2. consume all pending events (= queue becomes healthy again)
5261// 3. tap again -> block on ACTION_UP again -> receive ANR second time
5262TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
5263 tapOnWindow();
5264
5265 mWindow->consumeMotionDown();
5266 // Block on ACTION_UP
5267 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005268 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005269 mWindow->consumeMotionUp(); // Now the connection should be healthy again
5270 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005271 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005272 mWindow->assertNoEvents();
5273
5274 tapOnWindow();
5275 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005276 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005277 mWindow->consumeMotionUp();
5278
5279 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005280 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005281 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005282 mWindow->assertNoEvents();
5283}
5284
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005285// If a connection remains unresponsive for a while, make sure policy is only notified once about
5286// it.
5287TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005289 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5290 WINDOW_LOCATION));
5291
5292 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005293 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005294 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005295 // 'notifyConnectionUnresponsive' should only be called once per connection
5296 mFakePolicy->assertNotifyAnrWasNotCalled();
5297 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005298 mWindow->consumeMotionDown();
5299 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
5300 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5301 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005302 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005303 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005304 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005305}
5306
5307/**
5308 * If a window is processing a motion event, and then a key event comes in, the key event should
5309 * not to to the focused window until the motion is processed.
5310 *
5311 * Warning!!!
5312 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
5313 * and the injection timeout that we specify when injecting the key.
5314 * We must have the injection timeout (10ms) be smaller than
5315 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
5316 *
5317 * If that value changes, this test should also change.
5318 */
5319TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
5320 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
5321 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5322
5323 tapOnWindow();
5324 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
5325 ASSERT_TRUE(downSequenceNum);
5326 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
5327 ASSERT_TRUE(upSequenceNum);
5328 // Don't finish the events yet, and send a key
5329 // Injection will "succeed" because we will eventually give up and send the key to the focused
5330 // window even if motions are still being processed. But because the injection timeout is short,
5331 // we will receive INJECTION_TIMED_OUT as the result.
5332
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005333 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005334 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005335 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
5336 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005337 // Key will not be sent to the window, yet, because the window is still processing events
5338 // and the key remains pending, waiting for the touch events to be processed
5339 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
5340 ASSERT_FALSE(keySequenceNum);
5341
5342 std::this_thread::sleep_for(500ms);
5343 // if we wait long enough though, dispatcher will give up, and still send the key
5344 // to the focused window, even though we have not yet finished the motion event
5345 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5346 mWindow->finishEvent(*downSequenceNum);
5347 mWindow->finishEvent(*upSequenceNum);
5348}
5349
5350/**
5351 * If a window is processing a motion event, and then a key event comes in, the key event should
5352 * not go to the focused window until the motion is processed.
5353 * If then a new motion comes in, then the pending key event should be going to the currently
5354 * focused window right away.
5355 */
5356TEST_F(InputDispatcherSingleWindowAnr,
5357 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
5358 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
5359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5360
5361 tapOnWindow();
5362 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
5363 ASSERT_TRUE(downSequenceNum);
5364 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
5365 ASSERT_TRUE(upSequenceNum);
5366 // Don't finish the events yet, and send a key
5367 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005369 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005370 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005371 // At this point, key is still pending, and should not be sent to the application yet.
5372 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
5373 ASSERT_FALSE(keySequenceNum);
5374
5375 // Now tap down again. It should cause the pending key to go to the focused window right away.
5376 tapOnWindow();
5377 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
5378 // the other events yet. We can finish events in any order.
5379 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
5380 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
5381 mWindow->consumeMotionDown();
5382 mWindow->consumeMotionUp();
5383 mWindow->assertNoEvents();
5384}
5385
5386class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
5387 virtual void SetUp() override {
5388 InputDispatcherTest::SetUp();
5389
Chris Yea209fde2020-07-22 13:54:51 -07005390 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005391 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005392 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
5393 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005394 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005395 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005396 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005397
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005398 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
5399 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05005400 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005401 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005402
5403 // Set focused application.
5404 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07005405 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005406
5407 // Expect one focus window exist in display.
5408 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005409 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005410 mFocusedWindow->consumeFocusEvent(true);
5411 }
5412
5413 virtual void TearDown() override {
5414 InputDispatcherTest::TearDown();
5415
5416 mUnfocusedWindow.clear();
5417 mFocusedWindow.clear();
5418 }
5419
5420protected:
Chris Yea209fde2020-07-22 13:54:51 -07005421 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005422 sp<FakeWindowHandle> mUnfocusedWindow;
5423 sp<FakeWindowHandle> mFocusedWindow;
5424 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
5425 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
5426 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
5427
5428 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
5429
5430 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
5431
5432private:
5433 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005435 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5436 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005438 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5439 location));
5440 }
5441};
5442
5443// If we have 2 windows that are both unresponsive, the one with the shortest timeout
5444// should be ANR'd first.
5445TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005447 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5448 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005450 mFocusedWindow->consumeMotionDown();
5451 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5452 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5453 // We consumed all events, so no ANR
5454 ASSERT_TRUE(mDispatcher->waitForIdle());
5455 mFakePolicy->assertNotifyAnrWasNotCalled();
5456
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005458 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5459 FOCUSED_WINDOW_LOCATION));
5460 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
5461 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005462
5463 const std::chrono::duration timeout =
5464 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005465 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005466 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
5467 // sequence to make it consistent
5468 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005469 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005470 mFocusedWindow->consumeMotionDown();
5471 // This cancel is generated because the connection was unresponsive
5472 mFocusedWindow->consumeMotionCancel();
5473 mFocusedWindow->assertNoEvents();
5474 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005475 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005476 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5477 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005478 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005479}
5480
5481// If we have 2 windows with identical timeouts that are both unresponsive,
5482// it doesn't matter which order they should have ANR.
5483// But we should receive ANR for both.
5484TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
5485 // Set the timeout for unfocused window to match the focused window
5486 mUnfocusedWindow->setDispatchingTimeout(10ms);
5487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
5488
5489 tapOnFocusedWindow();
5490 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08005491 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
5492 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
5493 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005494
5495 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005496 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
5497 mFocusedWindow->getToken() == anrConnectionToken2);
5498 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
5499 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005500
5501 ASSERT_TRUE(mDispatcher->waitForIdle());
5502 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005503
5504 mFocusedWindow->consumeMotionDown();
5505 mFocusedWindow->consumeMotionUp();
5506 mUnfocusedWindow->consumeMotionOutside();
5507
Prabir Pradhanedd96402022-02-15 01:46:16 -08005508 sp<IBinder> responsiveToken1, responsiveToken2;
5509 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
5510 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005511
5512 // Both applications should be marked as responsive, in any order
5513 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
5514 mFocusedWindow->getToken() == responsiveToken2);
5515 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
5516 mUnfocusedWindow->getToken() == responsiveToken2);
5517 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005518}
5519
5520// If a window is already not responding, the second tap on the same window should be ignored.
5521// We should also log an error to account for the dropped event (not tested here).
5522// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
5523TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
5524 tapOnFocusedWindow();
5525 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5526 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5527 // Receive the events, but don't respond
5528 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
5529 ASSERT_TRUE(downEventSequenceNum);
5530 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
5531 ASSERT_TRUE(upEventSequenceNum);
5532 const std::chrono::duration timeout =
5533 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005534 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005535
5536 // Tap once again
5537 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005538 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005539 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5540 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005541 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005542 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5543 FOCUSED_WINDOW_LOCATION));
5544 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
5545 // valid touch target
5546 mUnfocusedWindow->assertNoEvents();
5547
5548 // Consume the first tap
5549 mFocusedWindow->finishEvent(*downEventSequenceNum);
5550 mFocusedWindow->finishEvent(*upEventSequenceNum);
5551 ASSERT_TRUE(mDispatcher->waitForIdle());
5552 // The second tap did not go to the focused window
5553 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005554 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08005555 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5556 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005557 mFakePolicy->assertNotifyAnrWasNotCalled();
5558}
5559
5560// If you tap outside of all windows, there will not be ANR
5561TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005562 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005563 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5564 LOCATION_OUTSIDE_ALL_WINDOWS));
5565 ASSERT_TRUE(mDispatcher->waitForIdle());
5566 mFakePolicy->assertNotifyAnrWasNotCalled();
5567}
5568
5569// Since the focused window is paused, tapping on it should not produce any events
5570TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
5571 mFocusedWindow->setPaused(true);
5572 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
5573
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005574 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005575 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5576 FOCUSED_WINDOW_LOCATION));
5577
5578 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
5579 ASSERT_TRUE(mDispatcher->waitForIdle());
5580 // Should not ANR because the window is paused, and touches shouldn't go to it
5581 mFakePolicy->assertNotifyAnrWasNotCalled();
5582
5583 mFocusedWindow->assertNoEvents();
5584 mUnfocusedWindow->assertNoEvents();
5585}
5586
5587/**
5588 * If a window is processing a motion event, and then a key event comes in, the key event should
5589 * not to to the focused window until the motion is processed.
5590 * If a different window becomes focused at this time, the key should go to that window instead.
5591 *
5592 * Warning!!!
5593 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
5594 * and the injection timeout that we specify when injecting the key.
5595 * We must have the injection timeout (10ms) be smaller than
5596 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
5597 *
5598 * If that value changes, this test should also change.
5599 */
5600TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
5601 // Set a long ANR timeout to prevent it from triggering
5602 mFocusedWindow->setDispatchingTimeout(2s);
5603 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5604
5605 tapOnUnfocusedWindow();
5606 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
5607 ASSERT_TRUE(downSequenceNum);
5608 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
5609 ASSERT_TRUE(upSequenceNum);
5610 // Don't finish the events yet, and send a key
5611 // Injection will succeed because we will eventually give up and send the key to the focused
5612 // window even if motions are still being processed.
5613
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005614 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005615 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005616 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
5617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005618 // Key will not be sent to the window, yet, because the window is still processing events
5619 // and the key remains pending, waiting for the touch events to be processed
5620 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
5621 ASSERT_FALSE(keySequenceNum);
5622
5623 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07005624 mFocusedWindow->setFocusable(false);
5625 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005626 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005627 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005628
5629 // Focus events should precede the key events
5630 mUnfocusedWindow->consumeFocusEvent(true);
5631 mFocusedWindow->consumeFocusEvent(false);
5632
5633 // Finish the tap events, which should unblock dispatcher
5634 mUnfocusedWindow->finishEvent(*downSequenceNum);
5635 mUnfocusedWindow->finishEvent(*upSequenceNum);
5636
5637 // Now that all queues are cleared and no backlog in the connections, the key event
5638 // can finally go to the newly focused "mUnfocusedWindow".
5639 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5640 mFocusedWindow->assertNoEvents();
5641 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005642 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005643}
5644
5645// When the touch stream is split across 2 windows, and one of them does not respond,
5646// then ANR should be raised and the touch should be canceled for the unresponsive window.
5647// The other window should not be affected by that.
5648TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
5649 // Touch Window 1
5650 NotifyMotionArgs motionArgs =
5651 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5652 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
5653 mDispatcher->notifyMotion(&motionArgs);
5654 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5655 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5656
5657 // Touch Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005658 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5659 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005660 mDispatcher->notifyMotion(&motionArgs);
5661
5662 const std::chrono::duration timeout =
5663 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005664 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005665
5666 mUnfocusedWindow->consumeMotionDown();
5667 mFocusedWindow->consumeMotionDown();
5668 // Focused window may or may not receive ACTION_MOVE
5669 // But it should definitely receive ACTION_CANCEL due to the ANR
5670 InputEvent* event;
5671 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
5672 ASSERT_TRUE(moveOrCancelSequenceNum);
5673 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
5674 ASSERT_NE(nullptr, event);
5675 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
5676 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5677 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
5678 mFocusedWindow->consumeMotionCancel();
5679 } else {
5680 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
5681 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005682 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005683 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5684 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005685
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005686 mUnfocusedWindow->assertNoEvents();
5687 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005688 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005689}
5690
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005691/**
5692 * If we have no focused window, and a key comes in, we start the ANR timer.
5693 * The focused application should add a focused window before the timer runs out to prevent ANR.
5694 *
5695 * If the user touches another application during this time, the key should be dropped.
5696 * Next, if a new focused window comes in, without toggling the focused application,
5697 * then no ANR should occur.
5698 *
5699 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
5700 * but in some cases the policy may not update the focused application.
5701 */
5702TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
5703 std::shared_ptr<FakeApplicationHandle> focusedApplication =
5704 std::make_shared<FakeApplicationHandle>();
5705 focusedApplication->setDispatchingTimeout(60ms);
5706 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
5707 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
5708 mFocusedWindow->setFocusable(false);
5709
5710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5711 mFocusedWindow->consumeFocusEvent(false);
5712
5713 // Send a key. The ANR timer should start because there is no focused window.
5714 // 'focusedApplication' will get blamed if this timer completes.
5715 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005716 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005717 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005718 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
5719 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005721
5722 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
5723 // then the injected touches won't cause the focused event to get dropped.
5724 // The dispatcher only checks for whether the queue should be pruned upon queueing.
5725 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
5726 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
5727 // For this test, it means that the key would get delivered to the window once it becomes
5728 // focused.
5729 std::this_thread::sleep_for(10ms);
5730
5731 // Touch unfocused window. This should force the pending key to get dropped.
5732 NotifyMotionArgs motionArgs =
5733 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5734 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
5735 mDispatcher->notifyMotion(&motionArgs);
5736
5737 // We do not consume the motion right away, because that would require dispatcher to first
5738 // process (== drop) the key event, and by that time, ANR will be raised.
5739 // Set the focused window first.
5740 mFocusedWindow->setFocusable(true);
5741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5742 setFocusedWindow(mFocusedWindow);
5743 mFocusedWindow->consumeFocusEvent(true);
5744 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
5745 // to another application. This could be a bug / behaviour in the policy.
5746
5747 mUnfocusedWindow->consumeMotionDown();
5748
5749 ASSERT_TRUE(mDispatcher->waitForIdle());
5750 // Should not ANR because we actually have a focused window. It was just added too slowly.
5751 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
5752}
5753
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005754// These tests ensure we cannot send touch events to a window that's positioned behind a window
5755// that has feature NO_INPUT_CHANNEL.
5756// Layout:
5757// Top (closest to user)
5758// mNoInputWindow (above all windows)
5759// mBottomWindow
5760// Bottom (furthest from user)
5761class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
5762 virtual void SetUp() override {
5763 InputDispatcherTest::SetUp();
5764
5765 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005766 mNoInputWindow =
5767 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
5768 "Window without input channel", ADISPLAY_ID_DEFAULT,
5769 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08005770 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005771 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5772 // It's perfectly valid for this window to not have an associated input channel
5773
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005774 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
5775 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005776 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
5777
5778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5779 }
5780
5781protected:
5782 std::shared_ptr<FakeApplicationHandle> mApplication;
5783 sp<FakeWindowHandle> mNoInputWindow;
5784 sp<FakeWindowHandle> mBottomWindow;
5785};
5786
5787TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
5788 PointF touchedPoint = {10, 10};
5789
5790 NotifyMotionArgs motionArgs =
5791 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5792 ADISPLAY_ID_DEFAULT, {touchedPoint});
5793 mDispatcher->notifyMotion(&motionArgs);
5794
5795 mNoInputWindow->assertNoEvents();
5796 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
5797 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
5798 // and therefore should prevent mBottomWindow from receiving touches
5799 mBottomWindow->assertNoEvents();
5800}
5801
5802/**
5803 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
5804 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
5805 */
5806TEST_F(InputDispatcherMultiWindowOcclusionTests,
5807 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005808 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
5809 "Window with input channel and NO_INPUT_CHANNEL",
5810 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005811
Prabir Pradhan51e7db02022-02-07 06:02:57 -08005812 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005813 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5814 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5815
5816 PointF touchedPoint = {10, 10};
5817
5818 NotifyMotionArgs motionArgs =
5819 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5820 ADISPLAY_ID_DEFAULT, {touchedPoint});
5821 mDispatcher->notifyMotion(&motionArgs);
5822
5823 mNoInputWindow->assertNoEvents();
5824 mBottomWindow->assertNoEvents();
5825}
5826
Vishnu Nair958da932020-08-21 17:12:37 -07005827class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
5828protected:
5829 std::shared_ptr<FakeApplicationHandle> mApp;
5830 sp<FakeWindowHandle> mWindow;
5831 sp<FakeWindowHandle> mMirror;
5832
5833 virtual void SetUp() override {
5834 InputDispatcherTest::SetUp();
5835 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005836 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5837 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
5838 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07005839 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5840 mWindow->setFocusable(true);
5841 mMirror->setFocusable(true);
5842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5843 }
5844};
5845
5846TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
5847 // Request focus on a mirrored window
5848 setFocusedWindow(mMirror);
5849
5850 // window gets focused
5851 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5853 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005854 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
5855}
5856
5857// A focused & mirrored window remains focused only if the window and its mirror are both
5858// focusable.
5859TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
5860 setFocusedWindow(mMirror);
5861
5862 // window gets focused
5863 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5865 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005866 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5868 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005869 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5870
5871 mMirror->setFocusable(false);
5872 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5873
5874 // window loses focus since one of the windows associated with the token in not focusable
5875 mWindow->consumeFocusEvent(false);
5876
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005877 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5878 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005879 mWindow->assertNoEvents();
5880}
5881
5882// A focused & mirrored window remains focused until the window and its mirror both become
5883// invisible.
5884TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
5885 setFocusedWindow(mMirror);
5886
5887 // window gets focused
5888 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5890 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005891 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5893 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005894 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5895
5896 mMirror->setVisible(false);
5897 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5898
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5900 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005901 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5903 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005904 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5905
5906 mWindow->setVisible(false);
5907 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5908
5909 // window loses focus only after all windows associated with the token become invisible.
5910 mWindow->consumeFocusEvent(false);
5911
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005912 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5913 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005914 mWindow->assertNoEvents();
5915}
5916
5917// A focused & mirrored window remains focused until both windows are removed.
5918TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
5919 setFocusedWindow(mMirror);
5920
5921 // window gets focused
5922 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5924 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005925 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5927 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005928 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5929
5930 // single window is removed but the window token remains focused
5931 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
5932
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5934 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005935 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5937 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005938 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5939
5940 // Both windows are removed
5941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5942 mWindow->consumeFocusEvent(false);
5943
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005944 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5945 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005946 mWindow->assertNoEvents();
5947}
5948
5949// Focus request can be pending until one window becomes visible.
5950TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
5951 // Request focus on an invisible mirror.
5952 mWindow->setVisible(false);
5953 mMirror->setVisible(false);
5954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5955 setFocusedWindow(mMirror);
5956
5957 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07005959 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005960 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005961
5962 mMirror->setVisible(true);
5963 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5964
5965 // window gets focused
5966 mWindow->consumeFocusEvent(true);
5967 // window gets the pending key event
5968 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5969}
Prabir Pradhan99987712020-11-10 18:43:05 -08005970
5971class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
5972protected:
5973 std::shared_ptr<FakeApplicationHandle> mApp;
5974 sp<FakeWindowHandle> mWindow;
5975 sp<FakeWindowHandle> mSecondWindow;
5976
5977 void SetUp() override {
5978 InputDispatcherTest::SetUp();
5979 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005980 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08005981 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005982 mSecondWindow =
5983 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08005984 mSecondWindow->setFocusable(true);
5985
5986 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5987 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5988
5989 setFocusedWindow(mWindow);
5990 mWindow->consumeFocusEvent(true);
5991 }
5992
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005993 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5994 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005995 mDispatcher->notifyPointerCaptureChanged(&args);
5996 }
5997
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005998 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5999 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08006000 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006001 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
6002 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08006003 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006004 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08006005 }
6006};
6007
6008TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
6009 // Ensure that capture cannot be obtained for unfocused windows.
6010 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
6011 mFakePolicy->assertSetPointerCaptureNotCalled();
6012 mSecondWindow->assertNoEvents();
6013
6014 // Ensure that capture can be enabled from the focus window.
6015 requestAndVerifyPointerCapture(mWindow, true);
6016
6017 // Ensure that capture cannot be disabled from a window that does not have capture.
6018 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
6019 mFakePolicy->assertSetPointerCaptureNotCalled();
6020
6021 // Ensure that capture can be disabled from the window with capture.
6022 requestAndVerifyPointerCapture(mWindow, false);
6023}
6024
6025TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006026 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08006027
6028 setFocusedWindow(mSecondWindow);
6029
6030 // Ensure that the capture disabled event was sent first.
6031 mWindow->consumeCaptureEvent(false);
6032 mWindow->consumeFocusEvent(false);
6033 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006034 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08006035
6036 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006037 notifyPointerCaptureChanged({});
6038 notifyPointerCaptureChanged(request);
6039 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08006040 mWindow->assertNoEvents();
6041 mSecondWindow->assertNoEvents();
6042 mFakePolicy->assertSetPointerCaptureNotCalled();
6043}
6044
6045TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006046 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08006047
6048 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006049 notifyPointerCaptureChanged({});
6050 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08006051
6052 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006053 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08006054 mWindow->consumeCaptureEvent(false);
6055 mWindow->assertNoEvents();
6056}
6057
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006058TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
6059 requestAndVerifyPointerCapture(mWindow, true);
6060
6061 // The first window loses focus.
6062 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006063 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006064 mWindow->consumeCaptureEvent(false);
6065
6066 // Request Pointer Capture from the second window before the notification from InputReader
6067 // arrives.
6068 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006069 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006070
6071 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006072 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006073
6074 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006075 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006076
6077 mSecondWindow->consumeFocusEvent(true);
6078 mSecondWindow->consumeCaptureEvent(true);
6079}
6080
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006081TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
6082 // App repeatedly enables and disables capture.
6083 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6084 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6085 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
6086 mFakePolicy->assertSetPointerCaptureCalled(false);
6087 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6088 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6089
6090 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
6091 // first request is now stale, this should do nothing.
6092 notifyPointerCaptureChanged(firstRequest);
6093 mWindow->assertNoEvents();
6094
6095 // InputReader notifies that the second request was enabled.
6096 notifyPointerCaptureChanged(secondRequest);
6097 mWindow->consumeCaptureEvent(true);
6098}
6099
Prabir Pradhan7092e262022-05-03 16:51:09 +00006100TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
6101 requestAndVerifyPointerCapture(mWindow, true);
6102
6103 // App toggles pointer capture off and on.
6104 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
6105 mFakePolicy->assertSetPointerCaptureCalled(false);
6106
6107 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6108 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6109
6110 // InputReader notifies that the latest "enable" request was processed, while skipping over the
6111 // preceding "disable" request.
6112 notifyPointerCaptureChanged(enableRequest);
6113
6114 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
6115 // any notifications.
6116 mWindow->assertNoEvents();
6117}
6118
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006119class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
6120protected:
6121 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00006122
6123 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
6124 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
6125
6126 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
6127 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
6128
6129 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
6130 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
6131 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
6132 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
6133 MAXIMUM_OBSCURING_OPACITY);
6134
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006135 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006136 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006137 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006138
6139 sp<FakeWindowHandle> mTouchWindow;
6140
6141 virtual void SetUp() override {
6142 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006143 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006144 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
6145 }
6146
6147 virtual void TearDown() override {
6148 InputDispatcherTest::TearDown();
6149 mTouchWindow.clear();
6150 }
6151
chaviw3277faf2021-05-19 16:45:23 -05006152 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
6153 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006154 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006155 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006156 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006157 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006158 return window;
6159 }
6160
6161 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
6162 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
6163 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006164 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006165 // Generate an arbitrary PID based on the UID
6166 window->setOwnerInfo(1777 + (uid % 10000), uid);
6167 return window;
6168 }
6169
6170 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
6171 NotifyMotionArgs args =
6172 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6173 ADISPLAY_ID_DEFAULT, points);
6174 mDispatcher->notifyMotion(&args);
6175 }
6176};
6177
6178TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006179 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006180 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006181 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006182
6183 touch();
6184
6185 mTouchWindow->assertNoEvents();
6186}
6187
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006188TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00006189 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
6190 const sp<FakeWindowHandle>& w =
6191 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
6192 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6193
6194 touch();
6195
6196 mTouchWindow->assertNoEvents();
6197}
6198
6199TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006200 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
6201 const sp<FakeWindowHandle>& w =
6202 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
6203 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6204
6205 touch();
6206
6207 w->assertNoEvents();
6208}
6209
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006210TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006211 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
6212 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006213
6214 touch();
6215
6216 mTouchWindow->consumeAnyMotionDown();
6217}
6218
6219TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006220 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006222 w->setFrame(Rect(0, 0, 50, 50));
6223 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006224
6225 touch({PointF{100, 100}});
6226
6227 mTouchWindow->consumeAnyMotionDown();
6228}
6229
6230TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006231 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006232 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6234
6235 touch();
6236
6237 mTouchWindow->consumeAnyMotionDown();
6238}
6239
6240TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
6241 const sp<FakeWindowHandle>& w =
6242 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
6243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006244
6245 touch();
6246
6247 mTouchWindow->consumeAnyMotionDown();
6248}
6249
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006250TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
6251 const sp<FakeWindowHandle>& w =
6252 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
6253 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6254
6255 touch();
6256
6257 w->assertNoEvents();
6258}
6259
6260/**
6261 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
6262 * inside) while letting them pass-through. Note that even though touch passes through the occluding
6263 * window, the occluding window will still receive ACTION_OUTSIDE event.
6264 */
6265TEST_F(InputDispatcherUntrustedTouchesTest,
6266 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
6267 const sp<FakeWindowHandle>& w =
6268 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006269 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6271
6272 touch();
6273
6274 w->consumeMotionOutside();
6275}
6276
6277TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
6278 const sp<FakeWindowHandle>& w =
6279 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006280 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6282
6283 touch();
6284
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006285 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006286}
6287
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006288TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006289 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006290 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6291 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6293
6294 touch();
6295
6296 mTouchWindow->consumeAnyMotionDown();
6297}
6298
6299TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
6300 const sp<FakeWindowHandle>& w =
6301 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6302 MAXIMUM_OBSCURING_OPACITY);
6303 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006304
6305 touch();
6306
6307 mTouchWindow->consumeAnyMotionDown();
6308}
6309
6310TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006311 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006312 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6313 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006314 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6315
6316 touch();
6317
6318 mTouchWindow->assertNoEvents();
6319}
6320
6321TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
6322 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
6323 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006324 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
6325 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006326 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006327 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
6328 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6330
6331 touch();
6332
6333 mTouchWindow->assertNoEvents();
6334}
6335
6336TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
6337 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
6338 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006339 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
6340 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006341 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006342 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
6343 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006344 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6345
6346 touch();
6347
6348 mTouchWindow->consumeAnyMotionDown();
6349}
6350
6351TEST_F(InputDispatcherUntrustedTouchesTest,
6352 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
6353 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006354 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6355 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006356 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006357 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6358 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
6360
6361 touch();
6362
6363 mTouchWindow->consumeAnyMotionDown();
6364}
6365
6366TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
6367 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006368 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6369 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006370 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006371 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6372 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006374
6375 touch();
6376
6377 mTouchWindow->assertNoEvents();
6378}
6379
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006380TEST_F(InputDispatcherUntrustedTouchesTest,
6381 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
6382 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006383 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6384 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006385 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006386 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6387 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006388 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
6389
6390 touch();
6391
6392 mTouchWindow->assertNoEvents();
6393}
6394
6395TEST_F(InputDispatcherUntrustedTouchesTest,
6396 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
6397 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006398 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6399 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006400 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006401 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6402 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006403 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
6404
6405 touch();
6406
6407 mTouchWindow->consumeAnyMotionDown();
6408}
6409
6410TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
6411 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006412 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6413 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006414 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6415
6416 touch();
6417
6418 mTouchWindow->consumeAnyMotionDown();
6419}
6420
6421TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
6422 const sp<FakeWindowHandle>& w =
6423 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
6424 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6425
6426 touch();
6427
6428 mTouchWindow->consumeAnyMotionDown();
6429}
6430
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00006431TEST_F(InputDispatcherUntrustedTouchesTest,
6432 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
6433 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
6434 const sp<FakeWindowHandle>& w =
6435 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
6436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6437
6438 touch();
6439
6440 mTouchWindow->assertNoEvents();
6441}
6442
6443TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
6444 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
6445 const sp<FakeWindowHandle>& w =
6446 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
6447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6448
6449 touch();
6450
6451 mTouchWindow->consumeAnyMotionDown();
6452}
6453
6454TEST_F(InputDispatcherUntrustedTouchesTest,
6455 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
6456 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
6457 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006458 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6459 OPACITY_ABOVE_THRESHOLD);
6460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6461
6462 touch();
6463
6464 mTouchWindow->consumeAnyMotionDown();
6465}
6466
6467TEST_F(InputDispatcherUntrustedTouchesTest,
6468 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
6469 const sp<FakeWindowHandle>& w1 =
6470 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
6471 OPACITY_BELOW_THRESHOLD);
6472 const sp<FakeWindowHandle>& w2 =
6473 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6474 OPACITY_BELOW_THRESHOLD);
6475 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6476
6477 touch();
6478
6479 mTouchWindow->assertNoEvents();
6480}
6481
6482/**
6483 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
6484 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
6485 * (which alone would result in allowing touches) does not affect the blocking behavior.
6486 */
6487TEST_F(InputDispatcherUntrustedTouchesTest,
6488 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
6489 const sp<FakeWindowHandle>& wB =
6490 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
6491 OPACITY_BELOW_THRESHOLD);
6492 const sp<FakeWindowHandle>& wC =
6493 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6494 OPACITY_BELOW_THRESHOLD);
6495 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
6496
6497 touch();
6498
6499 mTouchWindow->assertNoEvents();
6500}
6501
6502/**
6503 * This test is testing that a window from a different UID but with same application token doesn't
6504 * block the touch. Apps can share the application token for close UI collaboration for example.
6505 */
6506TEST_F(InputDispatcherUntrustedTouchesTest,
6507 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
6508 const sp<FakeWindowHandle>& w =
6509 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
6510 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00006511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6512
6513 touch();
6514
6515 mTouchWindow->consumeAnyMotionDown();
6516}
6517
arthurhungb89ccb02020-12-30 16:19:01 +08006518class InputDispatcherDragTests : public InputDispatcherTest {
6519protected:
6520 std::shared_ptr<FakeApplicationHandle> mApp;
6521 sp<FakeWindowHandle> mWindow;
6522 sp<FakeWindowHandle> mSecondWindow;
6523 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006524 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006525 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
6526 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08006527
6528 void SetUp() override {
6529 InputDispatcherTest::SetUp();
6530 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006531 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08006532 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08006533
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006534 mSecondWindow =
6535 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08006536 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08006537
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006538 mSpyWindow =
6539 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006540 mSpyWindow->setSpy(true);
6541 mSpyWindow->setTrustedOverlay(true);
6542 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
6543
arthurhungb89ccb02020-12-30 16:19:01 +08006544 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006545 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08006546 }
6547
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006548 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
6549 switch (fromSource) {
6550 case AINPUT_SOURCE_TOUCHSCREEN:
6551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6552 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6553 ADISPLAY_ID_DEFAULT, {50, 50}))
6554 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6555 break;
6556 case AINPUT_SOURCE_STYLUS:
6557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6558 injectMotionEvent(
6559 mDispatcher,
6560 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
6561 AINPUT_SOURCE_STYLUS)
6562 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6563 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6564 .x(50)
6565 .y(50))
6566 .build()));
6567 break;
6568 case AINPUT_SOURCE_MOUSE:
6569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6570 injectMotionEvent(
6571 mDispatcher,
6572 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6573 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6574 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6575 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6576 .x(50)
6577 .y(50))
6578 .build()));
6579 break;
6580 default:
6581 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
6582 }
arthurhungb89ccb02020-12-30 16:19:01 +08006583
6584 // Window should receive motion event.
6585 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006586 // Spy window should also receive motion event
6587 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00006588 }
6589
6590 // Start performing drag, we will create a drag window and transfer touch to it.
6591 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
6592 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006593 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00006594 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006595 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00006596 }
arthurhungb89ccb02020-12-30 16:19:01 +08006597
6598 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006599 mDragWindow =
6600 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006601 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08006602 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006603 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08006604
6605 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00006606 bool transferred =
6607 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
6608 true /* isDragDrop */);
6609 if (transferred) {
6610 mWindow->consumeMotionCancel();
6611 mDragWindow->consumeMotionDown();
6612 }
6613 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08006614 }
6615};
6616
6617TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006618 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08006619
6620 // Move on window.
6621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6622 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6623 ADISPLAY_ID_DEFAULT, {50, 50}))
6624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6625 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6626 mWindow->consumeDragEvent(false, 50, 50);
6627 mSecondWindow->assertNoEvents();
6628
6629 // Move to another window.
6630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6631 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6632 ADISPLAY_ID_DEFAULT, {150, 50}))
6633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6634 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6635 mWindow->consumeDragEvent(true, 150, 50);
6636 mSecondWindow->consumeDragEvent(false, 50, 50);
6637
6638 // Move back to original window.
6639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6640 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6641 ADISPLAY_ID_DEFAULT, {50, 50}))
6642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6643 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6644 mWindow->consumeDragEvent(false, 50, 50);
6645 mSecondWindow->consumeDragEvent(true, -50, 50);
6646
6647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6648 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
6649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6650 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6651 mWindow->assertNoEvents();
6652 mSecondWindow->assertNoEvents();
6653}
6654
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006655TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006656 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006657
6658 // No cancel event after drag start
6659 mSpyWindow->assertNoEvents();
6660
6661 const MotionEvent secondFingerDownEvent =
6662 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6663 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6664 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6665 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
6666 .build();
6667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6668 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6669 InputEventInjectionSync::WAIT_FOR_RESULT))
6670 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6671
6672 // Receives cancel for first pointer after next pointer down
6673 mSpyWindow->consumeMotionCancel();
6674 mSpyWindow->consumeMotionDown();
6675
6676 mSpyWindow->assertNoEvents();
6677}
6678
arthurhungf452d0b2021-01-06 00:19:52 +08006679TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006680 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08006681
6682 // Move on window.
6683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6684 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6685 ADISPLAY_ID_DEFAULT, {50, 50}))
6686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6687 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6688 mWindow->consumeDragEvent(false, 50, 50);
6689 mSecondWindow->assertNoEvents();
6690
6691 // Move to another window.
6692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6693 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6694 ADISPLAY_ID_DEFAULT, {150, 50}))
6695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6696 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6697 mWindow->consumeDragEvent(true, 150, 50);
6698 mSecondWindow->consumeDragEvent(false, 50, 50);
6699
6700 // drop to another window.
6701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6702 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6703 {150, 50}))
6704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6705 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6706 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6707 mWindow->assertNoEvents();
6708 mSecondWindow->assertNoEvents();
6709}
6710
arthurhung6d4bed92021-03-17 11:59:33 +08006711TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006712 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08006713
6714 // Move on window and keep button pressed.
6715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6716 injectMotionEvent(mDispatcher,
6717 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6718 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6719 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6720 .x(50)
6721 .y(50))
6722 .build()))
6723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6724 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6725 mWindow->consumeDragEvent(false, 50, 50);
6726 mSecondWindow->assertNoEvents();
6727
6728 // Move to another window and release button, expect to drop item.
6729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6730 injectMotionEvent(mDispatcher,
6731 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6732 .buttonState(0)
6733 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6734 .x(150)
6735 .y(50))
6736 .build()))
6737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6738 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6739 mWindow->assertNoEvents();
6740 mSecondWindow->assertNoEvents();
6741 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6742
6743 // nothing to the window.
6744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6745 injectMotionEvent(mDispatcher,
6746 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
6747 .buttonState(0)
6748 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6749 .x(150)
6750 .y(50))
6751 .build()))
6752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6753 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6754 mWindow->assertNoEvents();
6755 mSecondWindow->assertNoEvents();
6756}
6757
Arthur Hung54745652022-04-20 07:17:41 +00006758TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006759 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08006760
6761 // Set second window invisible.
6762 mSecondWindow->setVisible(false);
6763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
6764
6765 // Move on window.
6766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6767 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6768 ADISPLAY_ID_DEFAULT, {50, 50}))
6769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6770 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6771 mWindow->consumeDragEvent(false, 50, 50);
6772 mSecondWindow->assertNoEvents();
6773
6774 // Move to another window.
6775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6776 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6777 ADISPLAY_ID_DEFAULT, {150, 50}))
6778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6779 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6780 mWindow->consumeDragEvent(true, 150, 50);
6781 mSecondWindow->assertNoEvents();
6782
6783 // drop to another window.
6784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6785 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6786 {150, 50}))
6787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6788 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6789 mFakePolicy->assertDropTargetEquals(nullptr);
6790 mWindow->assertNoEvents();
6791 mSecondWindow->assertNoEvents();
6792}
6793
Arthur Hung54745652022-04-20 07:17:41 +00006794TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006795 // Ensure window could track pointerIds if it didn't support split touch.
6796 mWindow->setPreventSplitting(true);
6797
Arthur Hung54745652022-04-20 07:17:41 +00006798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6799 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6800 {50, 50}))
6801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6802 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6803
6804 const MotionEvent secondFingerDownEvent =
6805 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6806 .displayId(ADISPLAY_ID_DEFAULT)
6807 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6808 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6809 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(75).y(50))
6810 .build();
6811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6812 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6813 InputEventInjectionSync::WAIT_FOR_RESULT))
6814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6815 mWindow->consumeMotionPointerDown(1 /* pointerIndex */);
6816
6817 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006818 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00006819}
6820
6821TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
6822 // First down on second window.
6823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6824 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6825 {150, 50}))
6826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6827
6828 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6829
6830 // Second down on first window.
6831 const MotionEvent secondFingerDownEvent =
6832 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6833 .displayId(ADISPLAY_ID_DEFAULT)
6834 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6835 .pointer(
6836 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6837 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6838 .build();
6839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6840 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6841 InputEventInjectionSync::WAIT_FOR_RESULT))
6842 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6843 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6844
6845 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006846 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00006847
6848 // Move on window.
6849 const MotionEvent secondFingerMoveEvent =
6850 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6851 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6852 .pointer(
6853 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6854 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6855 .build();
6856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6857 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
6858 InputEventInjectionSync::WAIT_FOR_RESULT));
6859 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6860 mWindow->consumeDragEvent(false, 50, 50);
6861 mSecondWindow->consumeMotionMove();
6862
6863 // Release the drag pointer should perform drop.
6864 const MotionEvent secondFingerUpEvent =
6865 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6866 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6867 .pointer(
6868 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6869 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6870 .build();
6871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6872 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
6873 InputEventInjectionSync::WAIT_FOR_RESULT));
6874 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6875 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
6876 mWindow->assertNoEvents();
6877 mSecondWindow->consumeMotionMove();
6878}
6879
Arthur Hung3915c1f2022-05-31 07:17:17 +00006880TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006881 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00006882
6883 // Update window of second display.
6884 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006885 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00006886 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
6887
6888 // Let second display has a touch state.
6889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6890 injectMotionEvent(mDispatcher,
6891 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
6892 AINPUT_SOURCE_TOUCHSCREEN)
6893 .displayId(SECOND_DISPLAY_ID)
6894 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6895 .x(100)
6896 .y(100))
6897 .build()));
6898 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
6899 SECOND_DISPLAY_ID, 0 /* expectedFlag */);
6900 // Update window again.
6901 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
6902
6903 // Move on window.
6904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6905 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6906 ADISPLAY_ID_DEFAULT, {50, 50}))
6907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6908 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6909 mWindow->consumeDragEvent(false, 50, 50);
6910 mSecondWindow->assertNoEvents();
6911
6912 // Move to another window.
6913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6914 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6915 ADISPLAY_ID_DEFAULT, {150, 50}))
6916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6917 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6918 mWindow->consumeDragEvent(true, 150, 50);
6919 mSecondWindow->consumeDragEvent(false, 50, 50);
6920
6921 // drop to another window.
6922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6923 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6924 {150, 50}))
6925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6926 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6927 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6928 mWindow->assertNoEvents();
6929 mSecondWindow->assertNoEvents();
6930}
6931
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006932TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
6933 startDrag(true, AINPUT_SOURCE_MOUSE);
6934 // Move on window.
6935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6936 injectMotionEvent(mDispatcher,
6937 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6938 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6939 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6940 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6941 .x(50)
6942 .y(50))
6943 .build()))
6944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6945 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6946 mWindow->consumeDragEvent(false, 50, 50);
6947 mSecondWindow->assertNoEvents();
6948
6949 // Move to another window.
6950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6951 injectMotionEvent(mDispatcher,
6952 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6953 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6954 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6955 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6956 .x(150)
6957 .y(50))
6958 .build()))
6959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6960 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6961 mWindow->consumeDragEvent(true, 150, 50);
6962 mSecondWindow->consumeDragEvent(false, 50, 50);
6963
6964 // drop to another window.
6965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6966 injectMotionEvent(mDispatcher,
6967 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
6968 .buttonState(0)
6969 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6970 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6971 .x(150)
6972 .y(50))
6973 .build()))
6974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6975 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6976 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6977 mWindow->assertNoEvents();
6978 mSecondWindow->assertNoEvents();
6979}
6980
Vishnu Nair062a8672021-09-03 16:07:44 -07006981class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
6982
6983TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
6984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006985 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6986 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006987 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07006988 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6989 window->setFocusable(true);
6990 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6991 setFocusedWindow(window);
6992 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6993
6994 // With the flag set, window should not get any input
6995 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6996 mDispatcher->notifyKey(&keyArgs);
6997 window->assertNoEvents();
6998
6999 NotifyMotionArgs motionArgs =
7000 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7001 ADISPLAY_ID_DEFAULT);
7002 mDispatcher->notifyMotion(&motionArgs);
7003 window->assertNoEvents();
7004
7005 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007006 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007007 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
7008
7009 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7010 mDispatcher->notifyKey(&keyArgs);
7011 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7012
7013 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7014 ADISPLAY_ID_DEFAULT);
7015 mDispatcher->notifyMotion(&motionArgs);
7016 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7017 window->assertNoEvents();
7018}
7019
7020TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
7021 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
7022 std::make_shared<FakeApplicationHandle>();
7023 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007024 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
7025 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07007026 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
7027 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007028 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007029 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007030 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7031 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007032 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007033 window->setOwnerInfo(222, 222);
7034 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7035 window->setFocusable(true);
7036 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7037 setFocusedWindow(window);
7038 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7039
7040 // With the flag set, window should not get any input
7041 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7042 mDispatcher->notifyKey(&keyArgs);
7043 window->assertNoEvents();
7044
7045 NotifyMotionArgs motionArgs =
7046 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7047 ADISPLAY_ID_DEFAULT);
7048 mDispatcher->notifyMotion(&motionArgs);
7049 window->assertNoEvents();
7050
7051 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007052 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7054
7055 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7056 mDispatcher->notifyKey(&keyArgs);
7057 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7058
7059 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7060 ADISPLAY_ID_DEFAULT);
7061 mDispatcher->notifyMotion(&motionArgs);
7062 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7063 window->assertNoEvents();
7064}
7065
7066TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
7067 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
7068 std::make_shared<FakeApplicationHandle>();
7069 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007070 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
7071 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07007072 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
7073 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007074 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007076 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7077 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007078 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007079 window->setOwnerInfo(222, 222);
7080 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7081 window->setFocusable(true);
7082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7083 setFocusedWindow(window);
7084 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7085
7086 // With the flag set, window should not get any input
7087 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7088 mDispatcher->notifyKey(&keyArgs);
7089 window->assertNoEvents();
7090
7091 NotifyMotionArgs motionArgs =
7092 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7093 ADISPLAY_ID_DEFAULT);
7094 mDispatcher->notifyMotion(&motionArgs);
7095 window->assertNoEvents();
7096
7097 // When the window is no longer obscured because it went on top, it should get input
7098 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
7099
7100 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7101 mDispatcher->notifyKey(&keyArgs);
7102 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7103
7104 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7105 ADISPLAY_ID_DEFAULT);
7106 mDispatcher->notifyMotion(&motionArgs);
7107 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7108 window->assertNoEvents();
7109}
7110
Antonio Kantekf16f2832021-09-28 04:39:20 +00007111class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
7112protected:
7113 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00007114 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00007115 sp<FakeWindowHandle> mWindow;
7116 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00007117 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00007118
7119 void SetUp() override {
7120 InputDispatcherTest::SetUp();
7121
7122 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00007123 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007124 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007125 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007126 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007127 mSecondWindow =
7128 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007129 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00007130 mThirdWindow =
7131 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
7132 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
7133 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007134
7135 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00007136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
7137 {SECOND_DISPLAY_ID, {mThirdWindow}}});
7138 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007139 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007140
Antonio Kantek15beb512022-06-13 22:35:41 +00007141 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00007142 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Antonio Kantek15beb512022-06-13 22:35:41 +00007143 WINDOW_UID, true /* hasPermission */,
7144 ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07007145 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
7146 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00007147 mThirdWindow->assertNoEvents();
7148 }
7149
7150 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
7151 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
7152 SECONDARY_WINDOW_UID, true /* hasPermission */,
7153 SECOND_DISPLAY_ID)) {
7154 mWindow->assertNoEvents();
7155 mSecondWindow->assertNoEvents();
7156 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07007157 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00007158 }
7159
Antonio Kantek15beb512022-06-13 22:35:41 +00007160 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
7161 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07007162 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
7163 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00007164 mWindow->consumeTouchModeEvent(inTouchMode);
7165 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00007166 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00007167 }
7168};
7169
Antonio Kantek26defcf2022-02-08 01:12:27 +00007170TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08007171 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00007172 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
7173 windowInfo.ownerPid, windowInfo.ownerUid,
7174 false /* hasPermission */);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007175}
7176
Antonio Kantek26defcf2022-02-08 01:12:27 +00007177TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
7178 const WindowInfo& windowInfo = *mWindow->getInfo();
7179 int32_t ownerPid = windowInfo.ownerPid;
7180 int32_t ownerUid = windowInfo.ownerUid;
7181 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
7182 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007183 ownerUid, false /*hasPermission*/,
7184 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00007185 mWindow->assertNoEvents();
7186 mSecondWindow->assertNoEvents();
7187}
7188
7189TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
7190 const WindowInfo& windowInfo = *mWindow->getInfo();
7191 int32_t ownerPid = windowInfo.ownerPid;
7192 int32_t ownerUid = windowInfo.ownerUid;
7193 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00007194 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
7195 ownerUid, true /*hasPermission*/);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007196}
7197
Antonio Kantekf16f2832021-09-28 04:39:20 +00007198TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08007199 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00007200 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
7201 windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007202 true /*hasPermission*/, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00007203 mWindow->assertNoEvents();
7204 mSecondWindow->assertNoEvents();
7205}
7206
Antonio Kantek15beb512022-06-13 22:35:41 +00007207TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
7208 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
7209 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
7210 windowInfo.ownerPid, windowInfo.ownerUid,
7211 true /*hasPermission*/, SECOND_DISPLAY_ID));
7212 mWindow->assertNoEvents();
7213 mSecondWindow->assertNoEvents();
7214 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
7215}
7216
Antonio Kantek48710e42022-03-24 14:19:30 -07007217TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
7218 // Interact with the window first.
7219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
7220 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7221 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7222
7223 // Then remove focus.
7224 mWindow->setFocusable(false);
7225 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7226
7227 // Assert that caller can switch touch mode by owning one of the last interacted window.
7228 const WindowInfo& windowInfo = *mWindow->getInfo();
7229 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
7230 windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007231 false /*hasPermission*/, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07007232}
7233
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007234class InputDispatcherSpyWindowTest : public InputDispatcherTest {
7235public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007236 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007237 std::shared_ptr<FakeApplicationHandle> application =
7238 std::make_shared<FakeApplicationHandle>();
7239 std::string name = "Fake Spy ";
7240 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007241 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
7242 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007243 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007244 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007245 return spy;
7246 }
7247
7248 sp<FakeWindowHandle> createForeground() {
7249 std::shared_ptr<FakeApplicationHandle> application =
7250 std::make_shared<FakeApplicationHandle>();
7251 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007252 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7253 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007254 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007255 return window;
7256 }
7257
7258private:
7259 int mSpyCount{0};
7260};
7261
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007262using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007263/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007264 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
7265 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007266TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
7267 ScopedSilentDeath _silentDeath;
7268
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007269 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007270 spy->setTrustedOverlay(false);
7271 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
7272 ".* not a trusted overlay");
7273}
7274
7275/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007276 * Input injection into a display with a spy window but no foreground windows should succeed.
7277 */
7278TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007279 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007280 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
7281
7282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7283 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7285 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7286}
7287
7288/**
7289 * Verify the order in which different input windows receive events. The touched foreground window
7290 * (if there is one) should always receive the event first. When there are multiple spy windows, the
7291 * spy windows will receive the event according to their Z-order, where the top-most spy window will
7292 * receive events before ones belows it.
7293 *
7294 * Here, we set up a scenario with four windows in the following Z order from the top:
7295 * spy1, spy2, window, spy3.
7296 * We then inject an event and verify that the foreground "window" receives it first, followed by
7297 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
7298 * window.
7299 */
7300TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
7301 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007302 auto spy1 = createSpy();
7303 auto spy2 = createSpy();
7304 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007305 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
7306 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
7307 const size_t numChannels = channels.size();
7308
Michael Wright8e9a8562022-02-09 13:44:29 +00007309 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007310 if (!epollFd.ok()) {
7311 FAIL() << "Failed to create epoll fd";
7312 }
7313
7314 for (size_t i = 0; i < numChannels; i++) {
7315 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
7316 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
7317 FAIL() << "Failed to add fd to epoll";
7318 }
7319 }
7320
7321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7322 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7324
7325 std::vector<size_t> eventOrder;
7326 std::vector<struct epoll_event> events(numChannels);
7327 for (;;) {
7328 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
7329 (100ms).count());
7330 if (nFds < 0) {
7331 FAIL() << "Failed to call epoll_wait";
7332 }
7333 if (nFds == 0) {
7334 break; // epoll_wait timed out
7335 }
7336 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07007337 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07007338 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007339 channels[i]->consumeMotionDown();
7340 }
7341 }
7342
7343 // Verify the order in which the events were received.
7344 EXPECT_EQ(3u, eventOrder.size());
7345 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
7346 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
7347 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
7348}
7349
7350/**
7351 * A spy window using the NOT_TOUCHABLE flag does not receive events.
7352 */
7353TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
7354 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007355 auto spy = createSpy();
7356 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7358
7359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7360 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7361 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7362 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7363 spy->assertNoEvents();
7364}
7365
7366/**
7367 * A spy window will only receive gestures that originate within its touchable region. Gestures that
7368 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
7369 * to the window.
7370 */
7371TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
7372 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007373 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007374 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
7375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7376
7377 // Inject an event outside the spy window's touchable region.
7378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7379 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7380 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7381 window->consumeMotionDown();
7382 spy->assertNoEvents();
7383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7384 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7386 window->consumeMotionUp();
7387 spy->assertNoEvents();
7388
7389 // Inject an event inside the spy window's touchable region.
7390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7391 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7392 {5, 10}))
7393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7394 window->consumeMotionDown();
7395 spy->consumeMotionDown();
7396}
7397
7398/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007399 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007400 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007401 */
7402TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
7403 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007404 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007405 auto spy = createSpy();
7406 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007407 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007408 spy->setFrame(Rect{0, 0, 20, 20});
7409 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7410
7411 // Inject an event outside the spy window's frame and touchable region.
7412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007413 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7414 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007415 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7416 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007417 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007418}
7419
7420/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007421 * Even when a spy window spans over multiple foreground windows, the spy should receive all
7422 * pointers that are down within its bounds.
7423 */
7424TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
7425 auto windowLeft = createForeground();
7426 windowLeft->setFrame({0, 0, 100, 200});
7427 auto windowRight = createForeground();
7428 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007429 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007430 spy->setFrame({0, 0, 200, 200});
7431 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
7432
7433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7434 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7435 {50, 50}))
7436 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7437 windowLeft->consumeMotionDown();
7438 spy->consumeMotionDown();
7439
7440 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007441 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007442 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7443 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7444 .pointer(
7445 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7446 .build();
7447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7448 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7449 InputEventInjectionSync::WAIT_FOR_RESULT))
7450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7451 windowRight->consumeMotionDown();
7452 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
7453}
7454
7455/**
7456 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
7457 * the spy should receive the second pointer with ACTION_DOWN.
7458 */
7459TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
7460 auto window = createForeground();
7461 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007462 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007463 spyRight->setFrame({100, 0, 200, 200});
7464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
7465
7466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7467 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7468 {50, 50}))
7469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7470 window->consumeMotionDown();
7471 spyRight->assertNoEvents();
7472
7473 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007474 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007475 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7476 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7477 .pointer(
7478 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7479 .build();
7480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7481 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7482 InputEventInjectionSync::WAIT_FOR_RESULT))
7483 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7484 window->consumeMotionPointerDown(1 /*pointerIndex*/);
7485 spyRight->consumeMotionDown();
7486}
7487
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007488/**
7489 * The spy window should not be able to affect whether or not touches are split. Only the foreground
7490 * windows should be allowed to control split touch.
7491 */
7492TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007493 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007494 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007495 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007496 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007497
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007498 auto window = createForeground();
7499 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007500
7501 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7502
7503 // First finger down, no window touched.
7504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7505 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7506 {100, 200}))
7507 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7508 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7509 window->assertNoEvents();
7510
7511 // Second finger down on window, the window should receive touch down.
7512 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007513 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007514 .displayId(ADISPLAY_ID_DEFAULT)
7515 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7516 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7517 .x(100)
7518 .y(200))
7519 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7520 .build();
7521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7522 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7523 InputEventInjectionSync::WAIT_FOR_RESULT))
7524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7525
7526 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7527 spy->consumeMotionPointerDown(1 /* pointerIndex */);
7528}
7529
7530/**
7531 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
7532 * do not receive key events.
7533 */
7534TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007535 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007536 spy->setFocusable(false);
7537
7538 auto window = createForeground();
7539 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7540 setFocusedWindow(window);
7541 window->consumeFocusEvent(true);
7542
7543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7544 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7545 window->consumeKeyDown(ADISPLAY_ID_NONE);
7546
7547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7548 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7549 window->consumeKeyUp(ADISPLAY_ID_NONE);
7550
7551 spy->assertNoEvents();
7552}
7553
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00007554using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
7555
7556/**
7557 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
7558 * are currently sent to any other windows - including other spy windows - will also be cancelled.
7559 */
7560TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
7561 auto window = createForeground();
7562 auto spy1 = createSpy();
7563 auto spy2 = createSpy();
7564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
7565
7566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7567 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7569 window->consumeMotionDown();
7570 spy1->consumeMotionDown();
7571 spy2->consumeMotionDown();
7572
7573 // Pilfer pointers from the second spy window.
7574 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
7575 spy2->assertNoEvents();
7576 spy1->consumeMotionCancel();
7577 window->consumeMotionCancel();
7578
7579 // The rest of the gesture should only be sent to the second spy window.
7580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7581 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7582 ADISPLAY_ID_DEFAULT))
7583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7584 spy2->consumeMotionMove();
7585 spy1->assertNoEvents();
7586 window->assertNoEvents();
7587}
7588
7589/**
7590 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
7591 * in the middle of the gesture.
7592 */
7593TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
7594 auto window = createForeground();
7595 auto spy = createSpy();
7596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7597
7598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7599 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7601 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7602 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7603
7604 window->releaseChannel();
7605
7606 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7607
7608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7609 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7610 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7611 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7612}
7613
7614/**
7615 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
7616 * the spy, but not to any other windows.
7617 */
7618TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
7619 auto spy = createSpy();
7620 auto window = createForeground();
7621
7622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7623
7624 // First finger down on the window and the spy.
7625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7626 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7627 {100, 200}))
7628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7629 spy->consumeMotionDown();
7630 window->consumeMotionDown();
7631
7632 // Spy window pilfers the pointers.
7633 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7634 window->consumeMotionCancel();
7635
7636 // Second finger down on the window and spy, but the window should not receive the pointer down.
7637 const MotionEvent secondFingerDownEvent =
7638 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7639 .displayId(ADISPLAY_ID_DEFAULT)
7640 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7641 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7642 .x(100)
7643 .y(200))
7644 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7645 .build();
7646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7647 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7648 InputEventInjectionSync::WAIT_FOR_RESULT))
7649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7650
7651 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
7652
7653 // Third finger goes down outside all windows, so injection should fail.
7654 const MotionEvent thirdFingerDownEvent =
7655 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7656 .displayId(ADISPLAY_ID_DEFAULT)
7657 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7658 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7659 .x(100)
7660 .y(200))
7661 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7662 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
7663 .build();
7664 ASSERT_EQ(InputEventInjectionResult::FAILED,
7665 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
7666 InputEventInjectionSync::WAIT_FOR_RESULT))
7667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7668
7669 spy->assertNoEvents();
7670 window->assertNoEvents();
7671}
7672
7673/**
7674 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
7675 */
7676TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
7677 auto spy = createSpy();
7678 spy->setFrame(Rect(0, 0, 100, 100));
7679 auto window = createForeground();
7680 window->setFrame(Rect(0, 0, 200, 200));
7681
7682 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7683
7684 // First finger down on the window only
7685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7686 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7687 {150, 150}))
7688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7689 window->consumeMotionDown();
7690
7691 // Second finger down on the spy and window
7692 const MotionEvent secondFingerDownEvent =
7693 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7694 .displayId(ADISPLAY_ID_DEFAULT)
7695 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7696 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7697 .x(150)
7698 .y(150))
7699 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7700 .build();
7701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7702 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7703 InputEventInjectionSync::WAIT_FOR_RESULT))
7704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7705 spy->consumeMotionDown();
7706 window->consumeMotionPointerDown(1);
7707
7708 // Third finger down on the spy and window
7709 const MotionEvent thirdFingerDownEvent =
7710 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7711 .displayId(ADISPLAY_ID_DEFAULT)
7712 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7713 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7714 .x(150)
7715 .y(150))
7716 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7717 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7718 .build();
7719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7720 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
7721 InputEventInjectionSync::WAIT_FOR_RESULT))
7722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7723 spy->consumeMotionPointerDown(1);
7724 window->consumeMotionPointerDown(2);
7725
7726 // Spy window pilfers the pointers.
7727 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7728 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7729 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7730
7731 spy->assertNoEvents();
7732 window->assertNoEvents();
7733}
7734
7735/**
7736 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
7737 * other windows should be canceled. If this results in the cancellation of all pointers for some
7738 * window, then that window should receive ACTION_CANCEL.
7739 */
7740TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
7741 auto spy = createSpy();
7742 spy->setFrame(Rect(0, 0, 100, 100));
7743 auto window = createForeground();
7744 window->setFrame(Rect(0, 0, 200, 200));
7745
7746 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7747
7748 // First finger down on both spy and window
7749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7750 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7751 {10, 10}))
7752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7753 window->consumeMotionDown();
7754 spy->consumeMotionDown();
7755
7756 // Second finger down on the spy and window
7757 const MotionEvent secondFingerDownEvent =
7758 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7759 .displayId(ADISPLAY_ID_DEFAULT)
7760 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7761 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7762 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7763 .build();
7764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7765 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7766 InputEventInjectionSync::WAIT_FOR_RESULT))
7767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7768 spy->consumeMotionPointerDown(1);
7769 window->consumeMotionPointerDown(1);
7770
7771 // Spy window pilfers the pointers.
7772 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7773 window->consumeMotionCancel();
7774
7775 spy->assertNoEvents();
7776 window->assertNoEvents();
7777}
7778
7779/**
7780 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
7781 * be sent to other windows
7782 */
7783TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
7784 auto spy = createSpy();
7785 spy->setFrame(Rect(0, 0, 100, 100));
7786 auto window = createForeground();
7787 window->setFrame(Rect(0, 0, 200, 200));
7788
7789 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7790
7791 // First finger down on both window and spy
7792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7793 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7794 {10, 10}))
7795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7796 window->consumeMotionDown();
7797 spy->consumeMotionDown();
7798
7799 // Spy window pilfers the pointers.
7800 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7801 window->consumeMotionCancel();
7802
7803 // Second finger down on the window only
7804 const MotionEvent secondFingerDownEvent =
7805 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7806 .displayId(ADISPLAY_ID_DEFAULT)
7807 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7808 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7809 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
7810 .x(150)
7811 .y(150))
7812 .build();
7813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7814 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7815 InputEventInjectionSync::WAIT_FOR_RESULT))
7816 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7817 window->consumeMotionDown();
7818 window->assertNoEvents();
7819
7820 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
7821 spy->consumeMotionMove();
7822 spy->assertNoEvents();
7823}
7824
Prabir Pradhand65552b2021-10-07 11:23:50 -07007825class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
7826public:
7827 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
7828 std::shared_ptr<FakeApplicationHandle> overlayApplication =
7829 std::make_shared<FakeApplicationHandle>();
7830 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007831 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
7832 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007833 overlay->setFocusable(false);
7834 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007835 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007836 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007837 overlay->setTrustedOverlay(true);
7838
7839 std::shared_ptr<FakeApplicationHandle> application =
7840 std::make_shared<FakeApplicationHandle>();
7841 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007842 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
7843 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007844 window->setFocusable(true);
7845 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007846
7847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7848 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7849 setFocusedWindow(window);
7850 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7851 return {std::move(overlay), std::move(window)};
7852 }
7853
7854 void sendFingerEvent(int32_t action) {
7855 NotifyMotionArgs motionArgs =
7856 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
7857 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
7858 mDispatcher->notifyMotion(&motionArgs);
7859 }
7860
7861 void sendStylusEvent(int32_t action) {
7862 NotifyMotionArgs motionArgs =
7863 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
7864 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
7865 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
7866 mDispatcher->notifyMotion(&motionArgs);
7867 }
7868};
7869
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007870using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
7871
7872TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
7873 ScopedSilentDeath _silentDeath;
7874
Prabir Pradhand65552b2021-10-07 11:23:50 -07007875 auto [overlay, window] = setupStylusOverlayScenario();
7876 overlay->setTrustedOverlay(false);
7877 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
7878 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
7879 ".* not a trusted overlay");
7880}
7881
7882TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
7883 auto [overlay, window] = setupStylusOverlayScenario();
7884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7885
7886 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
7887 overlay->consumeMotionDown();
7888 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
7889 overlay->consumeMotionUp();
7890
7891 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
7892 window->consumeMotionDown();
7893 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
7894 window->consumeMotionUp();
7895
7896 overlay->assertNoEvents();
7897 window->assertNoEvents();
7898}
7899
7900TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
7901 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007902 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07007903 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7904
7905 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
7906 overlay->consumeMotionDown();
7907 window->consumeMotionDown();
7908 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
7909 overlay->consumeMotionUp();
7910 window->consumeMotionUp();
7911
7912 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
7913 window->consumeMotionDown();
7914 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
7915 window->consumeMotionUp();
7916
7917 overlay->assertNoEvents();
7918 window->assertNoEvents();
7919}
7920
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00007921/**
7922 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
7923 * The scenario is as follows:
7924 * - The stylus interceptor overlay is configured as a spy window.
7925 * - The stylus interceptor spy receives the start of a new stylus gesture.
7926 * - It pilfers pointers and then configures itself to no longer be a spy.
7927 * - The stylus interceptor continues to receive the rest of the gesture.
7928 */
7929TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
7930 auto [overlay, window] = setupStylusOverlayScenario();
7931 overlay->setSpy(true);
7932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7933
7934 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
7935 overlay->consumeMotionDown();
7936 window->consumeMotionDown();
7937
7938 // The interceptor pilfers the pointers.
7939 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
7940 window->consumeMotionCancel();
7941
7942 // The interceptor configures itself so that it is no longer a spy.
7943 overlay->setSpy(false);
7944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
7945
7946 // It continues to receive the rest of the stylus gesture.
7947 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
7948 overlay->consumeMotionMove();
7949 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
7950 overlay->consumeMotionUp();
7951
7952 window->assertNoEvents();
7953}
7954
Prabir Pradhan5735a322022-04-11 17:23:34 +00007955struct User {
7956 int32_t mPid;
7957 int32_t mUid;
7958 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
7959 std::unique_ptr<InputDispatcher>& mDispatcher;
7960
7961 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
7962 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
7963
7964 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
7965 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
7966 ADISPLAY_ID_DEFAULT, {100, 200},
7967 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7968 AMOTION_EVENT_INVALID_CURSOR_POSITION},
7969 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
7970 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
7971 }
7972
7973 InputEventInjectionResult injectTargetedKey(int32_t action) const {
7974 return inputdispatcher::injectKey(mDispatcher, action, 0 /* repeatCount*/, ADISPLAY_ID_NONE,
7975 InputEventInjectionSync::WAIT_FOR_RESULT,
7976 INJECT_EVENT_TIMEOUT, false /*allowKeyRepeat*/, {mUid},
7977 mPolicyFlags);
7978 }
7979
7980 sp<FakeWindowHandle> createWindow() const {
7981 std::shared_ptr<FakeApplicationHandle> overlayApplication =
7982 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007983 sp<FakeWindowHandle> window =
7984 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
7985 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00007986 window->setOwnerInfo(mPid, mUid);
7987 return window;
7988 }
7989};
7990
7991using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
7992
7993TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
7994 auto owner = User(mDispatcher, 10, 11);
7995 auto window = owner.createWindow();
7996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
7997
7998 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
7999 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8000 window->consumeMotionDown();
8001
8002 setFocusedWindow(window);
8003 window->consumeFocusEvent(true);
8004
8005 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8006 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
8007 window->consumeKeyDown(ADISPLAY_ID_NONE);
8008}
8009
8010TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
8011 auto owner = User(mDispatcher, 10, 11);
8012 auto window = owner.createWindow();
8013 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8014
8015 auto rando = User(mDispatcher, 20, 21);
8016 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
8017 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8018
8019 setFocusedWindow(window);
8020 window->consumeFocusEvent(true);
8021
8022 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
8023 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
8024 window->assertNoEvents();
8025}
8026
8027TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
8028 auto owner = User(mDispatcher, 10, 11);
8029 auto window = owner.createWindow();
8030 auto spy = owner.createWindow();
8031 spy->setSpy(true);
8032 spy->setTrustedOverlay(true);
8033 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8034
8035 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8036 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8037 spy->consumeMotionDown();
8038 window->consumeMotionDown();
8039}
8040
8041TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
8042 auto owner = User(mDispatcher, 10, 11);
8043 auto window = owner.createWindow();
8044
8045 auto rando = User(mDispatcher, 20, 21);
8046 auto randosSpy = rando.createWindow();
8047 randosSpy->setSpy(true);
8048 randosSpy->setTrustedOverlay(true);
8049 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
8050
8051 // The event is targeted at owner's window, so injection should succeed, but the spy should
8052 // not receive the event.
8053 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8054 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8055 randosSpy->assertNoEvents();
8056 window->consumeMotionDown();
8057}
8058
8059TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
8060 auto owner = User(mDispatcher, 10, 11);
8061 auto window = owner.createWindow();
8062
8063 auto rando = User(mDispatcher, 20, 21);
8064 auto randosSpy = rando.createWindow();
8065 randosSpy->setSpy(true);
8066 randosSpy->setTrustedOverlay(true);
8067 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
8068
8069 // A user that has injection permission can inject into any window.
8070 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8071 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8072 ADISPLAY_ID_DEFAULT));
8073 randosSpy->consumeMotionDown();
8074 window->consumeMotionDown();
8075
8076 setFocusedWindow(randosSpy);
8077 randosSpy->consumeFocusEvent(true);
8078
8079 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
8080 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
8081 window->assertNoEvents();
8082}
8083
8084TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
8085 auto owner = User(mDispatcher, 10, 11);
8086 auto window = owner.createWindow();
8087
8088 auto rando = User(mDispatcher, 20, 21);
8089 auto randosWindow = rando.createWindow();
8090 randosWindow->setFrame(Rect{-10, -10, -5, -5});
8091 randosWindow->setWatchOutsideTouch(true);
8092 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
8093
8094 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
8095 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8096 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8097 window->consumeMotionDown();
8098 randosWindow->consumeMotionOutside();
8099}
8100
Garfield Tane84e6f92019-08-29 17:28:41 -07008101} // namespace android::inputdispatcher