blob: e41df7c8dfc97bdce3f6997f93b2789d8d009e21 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Prabir Pradhan9205e422023-05-16 20:06:13 +000019#include "EventBuilders.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070021#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080022#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080023#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070024#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070025#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000026#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080027#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000098static constexpr int32_t WINDOW_PID = 999;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000099static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000100
Antonio Kantek15beb512022-06-13 22:35:41 +0000101// The default pid and uid for the windows created on the secondary display by the test.
102static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000103static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000104
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000105// An arbitrary pid of the gesture monitor window
106static constexpr int32_t MONITOR_PID = 2001;
107
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800108static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
109
Arthur Hungc539dbb2022-12-08 07:45:36 +0000110static constexpr int expectedWallpaperFlags =
111 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
112
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800113using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
114
chaviwd1c23182019-12-20 18:44:56 -0800115struct PointF {
116 float x;
117 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800118 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800119};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120
Gang Wang342c9272020-01-13 13:15:04 -0500121/**
122 * Return a DOWN key event with KEYCODE_A.
123 */
124static KeyEvent getTestKeyEvent() {
125 KeyEvent event;
126
Garfield Tanfbe732e2020-01-24 11:26:14 -0800127 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
128 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
129 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500130 return event;
131}
132
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000133static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
134 ASSERT_EQ(expectedAction, receivedAction)
135 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
136 << MotionEvent::actionToString(receivedAction);
137}
138
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800139MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
140 bool matches = action == arg.getAction();
141 if (!matches) {
142 *result_listener << "expected action " << MotionEvent::actionToString(action)
143 << ", but got " << MotionEvent::actionToString(arg.getAction());
144 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800145 if (action == AMOTION_EVENT_ACTION_DOWN) {
146 if (!matches) {
147 *result_listener << "; ";
148 }
149 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
150 matches &= arg.getDownTime() == arg.getEventTime();
151 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800152 if (action == AMOTION_EVENT_ACTION_CANCEL) {
153 if (!matches) {
154 *result_listener << "; ";
155 }
156 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
157 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
158 }
159 return matches;
160}
161
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800162MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
163 return arg.getDownTime() == downTime;
164}
165
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800166MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
167 return arg.getDisplayId() == displayId;
168}
169
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800170MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
171 return arg.getDeviceId() == deviceId;
172}
173
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800174MATCHER_P(WithSource, source, "InputEvent with specified source") {
175 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
176 << inputEventSourceToString(arg.getSource());
177 return arg.getSource() == source;
178}
179
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800180MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
181 return arg.getFlags() == flags;
182}
183
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800184MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
185 if (arg.getPointerCount() != 1) {
186 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
187 return false;
188 }
Harry Cutts33476232023-01-30 19:57:29 +0000189 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800190}
191
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800192MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
193 return arg.getPointerCount() == pointerCount;
194}
195
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800196MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
197 // Build a map for the received pointers, by pointer id
198 std::map<int32_t /*pointerId*/, PointF> actualPointers;
199 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
200 const int32_t pointerId = arg.getPointerId(pointerIndex);
201 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
202 }
203 return pointers == actualPointers;
204}
205
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206// --- FakeInputDispatcherPolicy ---
207
208class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800209 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
210
Michael Wrightd02c5b62014-02-10 15:10:22 -0800211public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000212 FakeInputDispatcherPolicy() = default;
213 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800214
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800215 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700216 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700217 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700218 EXPECT_EQ(event.getDisplayId(), args.displayId);
219
220 const auto& keyEvent = static_cast<const KeyEvent&>(event);
221 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
222 EXPECT_EQ(keyEvent.getAction(), args.action);
223 });
Jackal Guof9696682018-10-05 12:23:23 +0800224 }
225
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700226 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
227 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700228 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700229 EXPECT_EQ(event.getDisplayId(), args.displayId);
230
231 const auto& motionEvent = static_cast<const MotionEvent&>(event);
232 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
233 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000234 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
235 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
236 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
237 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700238 });
Jackal Guof9696682018-10-05 12:23:23 +0800239 }
240
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700241 void assertFilterInputEventWasNotCalled() {
242 std::scoped_lock lock(mLock);
243 ASSERT_EQ(nullptr, mFilteredEvent);
244 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800245
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800246 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700247 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 ASSERT_TRUE(mConfigurationChangedTime)
249 << "Timed out waiting for configuration changed call";
250 ASSERT_EQ(*mConfigurationChangedTime, when);
251 mConfigurationChangedTime = std::nullopt;
252 }
253
254 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700255 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800256 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800257 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800258 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
259 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
260 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
261 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
262 mLastNotifySwitch = std::nullopt;
263 }
264
chaviwfd6d3512019-03-25 13:23:49 -0700265 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700266 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800267 ASSERT_EQ(touchedToken, mOnPointerDownToken);
268 mOnPointerDownToken.clear();
269 }
270
271 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700272 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800273 ASSERT_TRUE(mOnPointerDownToken == nullptr)
274 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700275 }
276
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700277 // This function must be called soon after the expected ANR timer starts,
278 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500279 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700280 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 std::unique_lock lock(mLock);
283 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800285 ASSERT_NO_FATAL_FAILURE(
286 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500287 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700288 }
289
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000290 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800291 const sp<WindowInfoHandle>& window) {
292 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
293 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
294 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500295 }
296
Prabir Pradhanedd96402022-02-15 01:46:16 -0800297 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
298 const sp<IBinder>& expectedToken,
299 int32_t expectedPid) {
300 std::unique_lock lock(mLock);
301 android::base::ScopedLockAssertion assumeLocked(mLock);
302 AnrResult result;
303 ASSERT_NO_FATAL_FAILURE(result =
304 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
305 const auto& [token, pid] = result;
306 ASSERT_EQ(expectedToken, token);
307 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500308 }
309
Prabir Pradhanedd96402022-02-15 01:46:16 -0800310 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000311 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500312 std::unique_lock lock(mLock);
313 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800314 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
315 const auto& [token, _] = result;
316 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000317 }
318
Prabir Pradhanedd96402022-02-15 01:46:16 -0800319 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
320 int32_t expectedPid) {
321 std::unique_lock lock(mLock);
322 android::base::ScopedLockAssertion assumeLocked(mLock);
323 AnrResult result;
324 ASSERT_NO_FATAL_FAILURE(
325 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
326 const auto& [token, pid] = result;
327 ASSERT_EQ(expectedToken, token);
328 ASSERT_EQ(expectedPid, pid);
329 }
330
331 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000332 sp<IBinder> getResponsiveWindowToken() {
333 std::unique_lock lock(mLock);
334 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800335 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
336 const auto& [token, _] = result;
337 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700338 }
339
340 void assertNotifyAnrWasNotCalled() {
341 std::scoped_lock lock(mLock);
342 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800343 ASSERT_TRUE(mAnrWindows.empty());
344 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500345 << "ANR was not called, but please also consume the 'connection is responsive' "
346 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700347 }
348
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000349 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800350 std::unique_lock lock(mLock);
351 base::ScopedLockAssertion assumeLocked(mLock);
352
353 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
354 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000355 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800356 enabled;
357 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000358 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
359 << ") to be called.";
360 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800361 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 auto request = *mPointerCaptureRequest;
363 mPointerCaptureRequest.reset();
364 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800365 }
366
367 void assertSetPointerCaptureNotCalled() {
368 std::unique_lock lock(mLock);
369 base::ScopedLockAssertion assumeLocked(mLock);
370
371 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000372 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800373 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
378
arthurhungf452d0b2021-01-06 00:19:52 +0800379 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
380 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800381 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800382 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800383 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800384 }
385
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800386 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
387 std::unique_lock lock(mLock);
388 base::ScopedLockAssertion assumeLocked(mLock);
389 std::optional<sp<IBinder>> receivedToken =
390 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
391 mNotifyInputChannelBroken);
392 ASSERT_TRUE(receivedToken.has_value());
393 ASSERT_EQ(token, *receivedToken);
394 }
395
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800396 /**
397 * Set policy timeout. A value of zero means next key will not be intercepted.
398 */
399 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
400 mInterceptKeyTimeout = timeout;
401 }
402
Josep del Riob3981622023-04-18 15:49:45 +0000403 void assertUserActivityPoked() {
404 std::scoped_lock lock(mLock);
405 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
406 }
407
408 void assertUserActivityNotPoked() {
409 std::scoped_lock lock(mLock);
410 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
411 }
412
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000413 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000414 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
415 }
416
417 void assertNotifyDeviceInteractionWasNotCalled() {
418 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
419 }
420
Michael Wrightd02c5b62014-02-10 15:10:22 -0800421private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700422 std::mutex mLock;
423 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
424 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
425 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
426 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800427
Prabir Pradhan99987712020-11-10 18:43:05 -0800428 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000429
430 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800431
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700432 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700433 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800434 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
435 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700436 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800437 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
438 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700439
arthurhungf452d0b2021-01-06 00:19:52 +0800440 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800441 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000442 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800443
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800444 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
445
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000446 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000447
Prabir Pradhanedd96402022-02-15 01:46:16 -0800448 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
449 // for a specific container to become non-empty. When the container is non-empty, return the
450 // first entry from the container and erase it.
451 template <class T>
452 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
453 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
454 // If there is an ANR, Dispatcher won't be idle because there are still events
455 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
456 // before checking if ANR was called.
457 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
458 // to provide it some time to act. 100ms seems reasonable.
459 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
460 const std::chrono::time_point start = std::chrono::steady_clock::now();
461 std::optional<T> token =
462 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
463 if (!token.has_value()) {
464 ADD_FAILURE() << "Did not receive the ANR callback";
465 return {};
466 }
467
468 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
469 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
470 // the dispatcher started counting before this function was called
471 if (std::chrono::abs(timeout - waited) > 100ms) {
472 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
473 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
474 << "ms, but waited "
475 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
476 << "ms instead";
477 }
478 return *token;
479 }
480
481 template <class T>
482 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
483 std::queue<T>& storage,
484 std::unique_lock<std::mutex>& lock,
485 std::condition_variable& condition)
486 REQUIRES(mLock) {
487 condition.wait_for(lock, timeout,
488 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
489 if (storage.empty()) {
490 ADD_FAILURE() << "Did not receive the expected callback";
491 return std::nullopt;
492 }
493 T item = storage.front();
494 storage.pop();
495 return std::make_optional(item);
496 }
497
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600498 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700499 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800500 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501 }
502
Prabir Pradhanedd96402022-02-15 01:46:16 -0800503 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
504 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700505 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800506 ASSERT_TRUE(pid.has_value());
507 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700508 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500509 }
510
Prabir Pradhanedd96402022-02-15 01:46:16 -0800511 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
512 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500513 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800514 ASSERT_TRUE(pid.has_value());
515 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500516 mNotifyAnr.notify_all();
517 }
518
519 void notifyNoFocusedWindowAnr(
520 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
521 std::scoped_lock lock(mLock);
522 mAnrApplications.push(applicationHandle);
523 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800524 }
525
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800526 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
527 std::scoped_lock lock(mLock);
528 mBrokenInputChannels.push(connectionToken);
529 mNotifyInputChannelBroken.notify_all();
530 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800531
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600532 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700533
Chris Yef59a2f42020-10-16 12:55:26 -0700534 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
535 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
536 const std::vector<float>& values) override {}
537
538 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
539 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000540
Chris Yefb552902021-02-03 17:18:37 -0800541 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
542
Prabir Pradhana41d2442023-04-20 21:30:40 +0000543 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700544 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700546 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000547 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
548 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800549 break;
550 }
551
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700552 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000553 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
554 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800555 break;
556 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700557 default: {
558 ADD_FAILURE() << "Should only filter keys or motions";
559 break;
560 }
Jackal Guof9696682018-10-05 12:23:23 +0800561 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800562 return true;
563 }
564
Prabir Pradhana41d2442023-04-20 21:30:40 +0000565 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
566 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800567 // Clear intercept state when we handled the event.
568 mInterceptKeyTimeout = 0ms;
569 }
570 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800571
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600572 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573
Prabir Pradhana41d2442023-04-20 21:30:40 +0000574 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800575 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
576 // Clear intercept state so we could dispatch the event in next wake.
577 mInterceptKeyTimeout = 0ms;
578 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579 }
580
Prabir Pradhana41d2442023-04-20 21:30:40 +0000581 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
582 uint32_t) override {
583 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800584 }
585
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600586 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
587 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700588 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800589 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
590 * essentially a passthrough for notifySwitch.
591 */
Harry Cutts33476232023-01-30 19:57:29 +0000592 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Josep del Riob3981622023-04-18 15:49:45 +0000595 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
596 std::scoped_lock lock(mLock);
597 mPokedUserActivity = true;
598 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600600 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700601 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700602 mOnPointerDownToken = newToken;
603 }
604
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000605 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800606 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000607 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800608 mPointerCaptureChangedCondition.notify_all();
609 }
610
arthurhungf452d0b2021-01-06 00:19:52 +0800611 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
612 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800613 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800614 mDropTargetWindowToken = token;
615 }
616
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000617 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000618 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000619 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
620 }
621
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700622 void assertFilterInputEventWasCalledInternal(
623 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700624 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800625 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700626 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800627 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800628 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629};
630
Michael Wrightd02c5b62014-02-10 15:10:22 -0800631// --- InputDispatcherTest ---
632
633class InputDispatcherTest : public testing::Test {
634protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000635 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700636 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800637
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000638 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000639 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
640 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800641 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000642 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700643 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800644 }
645
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000646 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700647 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000648 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700649 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800650 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700651
652 /**
653 * Used for debugging when writing the test
654 */
655 void dumpDispatcherState() {
656 std::string dump;
657 mDispatcher->dump(dump);
658 std::stringstream ss(dump);
659 std::string to;
660
661 while (std::getline(ss, to, '\n')) {
662 ALOGE("%s", to.c_str());
663 }
664 }
Vishnu Nair958da932020-08-21 17:12:37 -0700665
Chavi Weingarten847e8512023-03-29 00:26:09 +0000666 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700667 FocusRequest request;
668 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000669 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700670 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
671 request.displayId = window->getInfo()->displayId;
672 mDispatcher->setFocusedWindow(request);
673 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800674};
675
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
677 KeyEvent event;
678
679 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
683 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800684 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000685 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000686 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800687 << "Should reject key events with undefined action.";
688
689 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800690 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
691 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600692 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800693 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000694 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000695 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800696 << "Should reject key events with ACTION_MULTIPLE.";
697}
698
699TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
700 MotionEvent event;
701 PointerProperties pointerProperties[MAX_POINTERS + 1];
702 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800703 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800704 pointerProperties[i].clear();
705 pointerProperties[i].id = i;
706 pointerCoords[i].clear();
707 }
708
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800709 // Some constants commonly used below
710 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
711 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
712 constexpr int32_t metaState = AMETA_NONE;
713 constexpr MotionClassification classification = MotionClassification::NONE;
714
chaviw9eaa22c2020-07-01 16:21:27 -0700715 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800717 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700718 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
719 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700720 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
721 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700722 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800723 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000724 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800726 << "Should reject motion events with undefined action.";
727
728 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800730 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
731 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
732 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
733 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500734 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800735 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000736 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000737 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800738 << "Should reject motion events with pointer down index too large.";
739
Garfield Tanfbe732e2020-01-24 11:26:14 -0800740 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700741 AMOTION_EVENT_ACTION_POINTER_DOWN |
742 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700743 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
744 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700745 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500746 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800747 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000748 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000749 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800750 << "Should reject motion events with pointer down index too small.";
751
752 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800753 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800754 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
755 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
756 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
757 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500758 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800759 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000760 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000761 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800762 << "Should reject motion events with pointer up index too large.";
763
Garfield Tanfbe732e2020-01-24 11:26:14 -0800764 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700765 AMOTION_EVENT_ACTION_POINTER_UP |
766 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700767 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
768 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700769 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500770 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800771 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000772 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000773 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800774 << "Should reject motion events with pointer up index too small.";
775
776 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800777 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
778 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700779 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
781 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700782 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with 0 pointers.";
787
Garfield Tanfbe732e2020-01-24 11:26:14 -0800788 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
789 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700790 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700791 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
792 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700793 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800794 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000795 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000796 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800797 << "Should reject motion events with more than MAX_POINTERS pointers.";
798
799 // Rejects motion events with invalid pointer ids.
800 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800801 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
802 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700803 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700804 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
805 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700806 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800807 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000808 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000809 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800810 << "Should reject motion events with pointer ids less than 0.";
811
812 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800813 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
814 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700815 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700816 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
817 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700818 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800819 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000820 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000821 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800822 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
823
824 // Rejects motion events with duplicate pointer ids.
825 pointerProperties[0].id = 1;
826 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800827 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
828 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700829 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700830 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
831 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700832 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800833 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000834 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000835 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800836 << "Should reject motion events with duplicate pointer ids.";
837}
838
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800839/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
840
841TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
842 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000843 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800844 ASSERT_TRUE(mDispatcher->waitForIdle());
845
846 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
847}
848
849TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000850 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
851 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000852 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800853
854 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
855 args.policyFlags |= POLICY_FLAG_TRUSTED;
856 mFakePolicy->assertNotifySwitchWasCalled(args);
857}
858
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700859namespace {
860
Arthur Hungb92218b2018-08-14 12:00:21 +0800861// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700862static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700863// Default input dispatching timeout if there is no focused application or paused window
864// from which to determine an appropriate dispatching timeout.
865static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
866 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
867 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800868
869class FakeApplicationHandle : public InputApplicationHandle {
870public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 FakeApplicationHandle() {
872 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700873 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500874 mInfo.dispatchingTimeoutMillis =
875 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700876 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800877 virtual ~FakeApplicationHandle() {}
878
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000879 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500881 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
882 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700883 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800884};
885
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800886class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800887public:
Garfield Tan15601662020-09-22 15:32:38 -0700888 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800889 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700890 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800891 }
892
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800893 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700894 InputEvent* event;
895 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
896 if (!consumeSeq) {
897 return nullptr;
898 }
899 finishEvent(*consumeSeq);
900 return event;
901 }
902
903 /**
904 * Receive an event without acknowledging it.
905 * Return the sequence number that could later be used to send finished signal.
906 */
907 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800908 uint32_t consumeSeq;
909 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800910
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800911 std::chrono::time_point start = std::chrono::steady_clock::now();
912 status_t status = WOULD_BLOCK;
913 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000914 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915 &event);
916 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
917 if (elapsed > 100ms) {
918 break;
919 }
920 }
921
922 if (status == WOULD_BLOCK) {
923 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700924 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800925 }
926
927 if (status != OK) {
928 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700929 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930 }
931 if (event == nullptr) {
932 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700933 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800934 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700935 if (outEvent != nullptr) {
936 *outEvent = event;
937 }
938 return consumeSeq;
939 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800940
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700941 /**
942 * To be used together with "receiveEvent" to complete the consumption of an event.
943 */
944 void finishEvent(uint32_t consumeSeq) {
945 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
946 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800947 }
948
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000949 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
950 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
951 ASSERT_EQ(OK, status);
952 }
953
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700954 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000955 std::optional<int32_t> expectedDisplayId,
956 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800957 InputEvent* event = consume();
958
959 ASSERT_NE(nullptr, event) << mName.c_str()
960 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800961 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700962 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
963 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800964
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000965 if (expectedDisplayId.has_value()) {
966 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
967 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800968
Tiger Huang8664f8c2018-10-11 19:14:35 +0800969 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700970 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800971 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
972 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000973 if (expectedFlags.has_value()) {
974 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
975 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800976 break;
977 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700978 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800979 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000980 assertMotionAction(expectedAction, motionEvent.getAction());
981
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000982 if (expectedFlags.has_value()) {
983 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
984 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800985 break;
986 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700987 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100988 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
989 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700990 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800991 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
992 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700993 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000994 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800997 FAIL() << "Use 'consumeDragEvent' for DRAG events";
998 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800999 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001000 }
1001
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001002 MotionEvent* consumeMotion() {
1003 InputEvent* event = consume();
1004
1005 if (event == nullptr) {
1006 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1007 return nullptr;
1008 }
1009
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 if (event->getType() != InputEventType::MOTION) {
1011 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001012 return nullptr;
1013 }
1014 return static_cast<MotionEvent*>(event);
1015 }
1016
1017 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1018 MotionEvent* motionEvent = consumeMotion();
1019 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1020 ASSERT_THAT(*motionEvent, matcher);
1021 }
1022
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001023 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1024 InputEvent* event = consume();
1025 ASSERT_NE(nullptr, event) << mName.c_str()
1026 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001027 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1028 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001029
1030 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1031 << mName.c_str() << ": event displayId should always be NONE.";
1032
1033 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1034 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001035 }
1036
Prabir Pradhan99987712020-11-10 18:43:05 -08001037 void consumeCaptureEvent(bool hasCapture) {
1038 const InputEvent* event = consume();
1039 ASSERT_NE(nullptr, event) << mName.c_str()
1040 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001041 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1042 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001043
1044 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046
1047 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1048 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1049 }
1050
arthurhungb89ccb02020-12-30 16:19:01 +08001051 void consumeDragEvent(bool isExiting, float x, float y) {
1052 const InputEvent* event = consume();
1053 ASSERT_NE(nullptr, event) << mName.c_str()
1054 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001056
1057 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1058 << mName.c_str() << ": event displayId should always be NONE.";
1059
1060 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1061 EXPECT_EQ(isExiting, dragEvent.isExiting());
1062 EXPECT_EQ(x, dragEvent.getX());
1063 EXPECT_EQ(y, dragEvent.getY());
1064 }
1065
Antonio Kantekf16f2832021-09-28 04:39:20 +00001066 void consumeTouchModeEvent(bool inTouchMode) {
1067 const InputEvent* event = consume();
1068 ASSERT_NE(nullptr, event) << mName.c_str()
1069 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001070 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1071 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001072
1073 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1074 << mName.c_str() << ": event displayId should always be NONE.";
1075 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1076 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1077 }
1078
chaviwd1c23182019-12-20 18:44:56 -08001079 void assertNoEvents() {
1080 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001081 if (event == nullptr) {
1082 return;
1083 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001084 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001085 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1086 ADD_FAILURE() << "Received key event "
1087 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001088 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001089 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1090 ADD_FAILURE() << "Received motion event "
1091 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001092 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001093 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1094 ADD_FAILURE() << "Received focus event, hasFocus = "
1095 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001096 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001097 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1098 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1099 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001100 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001101 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1102 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1103 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001104 }
1105 FAIL() << mName.c_str()
1106 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001107 }
1108
1109 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1110
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001111 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1112
chaviwd1c23182019-12-20 18:44:56 -08001113protected:
1114 std::unique_ptr<InputConsumer> mConsumer;
1115 PreallocatedInputEventFactory mEventFactory;
1116
1117 std::string mName;
1118};
1119
chaviw3277faf2021-05-19 16:45:23 -05001120class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001121public:
1122 static const int32_t WIDTH = 600;
1123 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001124
Chris Yea209fde2020-07-22 13:54:51 -07001125 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001126 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001127 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001128 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001130 base::Result<std::unique_ptr<InputChannel>> channel =
1131 dispatcher->createInputChannel(name);
1132 token = (*channel)->getConnectionToken();
1133 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001134 }
1135
1136 inputApplicationHandle->updateInfo();
1137 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1138
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001139 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001140 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001141 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001142 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001143 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001144 mInfo.frameLeft = 0;
1145 mInfo.frameTop = 0;
1146 mInfo.frameRight = WIDTH;
1147 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001148 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001149 mInfo.globalScaleFactor = 1.0;
1150 mInfo.touchableRegion.clear();
1151 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001152 mInfo.ownerPid = WINDOW_PID;
1153 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001154 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001155 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001156 }
1157
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001158 sp<FakeWindowHandle> clone(int32_t displayId) {
1159 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1160 handle->mInfo = mInfo;
1161 handle->mInfo.displayId = displayId;
1162 handle->mInfo.id = sId++;
1163 handle->mInputReceiver = mInputReceiver;
1164 return handle;
1165 }
1166
1167 /**
1168 * This is different from clone, because clone will make a "mirror" window - a window with the
1169 * same token, but a different ID. The original window and the clone window are allowed to be
1170 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1171 * This function will create a different object of WindowInfoHandle, but with the same
1172 * properties as the original object - including the ID.
1173 * You can use either the old or the new object to consume the events.
1174 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1175 * at the same time inside dispatcher.
1176 */
1177 sp<FakeWindowHandle> duplicate() {
1178 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1179 handle->mInfo = mInfo;
1180 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001181 return handle;
1182 }
1183
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001184 void setTouchable(bool touchable) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1186 }
chaviwd1c23182019-12-20 18:44:56 -08001187
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001188 void setFocusable(bool focusable) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1190 }
1191
1192 void setVisible(bool visible) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1194 }
Vishnu Nair958da932020-08-21 17:12:37 -07001195
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001196 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001197 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001198 }
1199
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001200 void setPaused(bool paused) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1202 }
1203
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001204 void setPreventSplitting(bool preventSplitting) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001206 }
1207
1208 void setSlippery(bool slippery) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1210 }
1211
1212 void setWatchOutsideTouch(bool watchOutside) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1214 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001215
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001216 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1217
1218 void setInterceptsStylus(bool interceptsStylus) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1220 }
1221
1222 void setDropInput(bool dropInput) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1224 }
1225
1226 void setDropInputIfObscured(bool dropInputIfObscured) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1228 }
1229
1230 void setNoInputChannel(bool noInputChannel) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1232 }
1233
Josep del Riob3981622023-04-18 15:49:45 +00001234 void setDisableUserActivity(bool disableUserActivity) {
1235 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1236 }
1237
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001238 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1239
chaviw3277faf2021-05-19 16:45:23 -05001240 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001241
Bernardo Rufino7393d172021-02-26 13:56:11 +00001242 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1243
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001244 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001245 mInfo.frameLeft = frame.left;
1246 mInfo.frameTop = frame.top;
1247 mInfo.frameRight = frame.right;
1248 mInfo.frameBottom = frame.bottom;
1249 mInfo.touchableRegion.clear();
1250 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001251
1252 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1253 ui::Transform translate;
1254 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1255 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001256 }
1257
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001258 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1259
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001260 void setIsWallpaper(bool isWallpaper) {
1261 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1262 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001263
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001264 void setDupTouchToWallpaper(bool hasWallpaper) {
1265 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1266 }
chaviwd1c23182019-12-20 18:44:56 -08001267
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001268 void setTrustedOverlay(bool trustedOverlay) {
1269 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1270 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001271
chaviw9eaa22c2020-07-01 16:21:27 -07001272 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1273 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1274 }
1275
1276 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001277
yunho.shinf4a80b82020-11-16 21:13:57 +09001278 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1279
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001281 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001282 }
1283
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001284 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001285 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001286 }
1287
Svet Ganov5d3bc372020-01-26 23:11:07 -08001288 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001289 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001290 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1291 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001292 }
1293
1294 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001295 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001296 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1297 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001298 }
1299
1300 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001301 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001302 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1303 }
1304
1305 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1306 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001307 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001308 expectedFlags);
1309 }
1310
Svet Ganov5d3bc372020-01-26 23:11:07 -08001311 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1313 int32_t expectedFlags = 0) {
1314 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1315 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001316 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001317 }
1318
1319 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001320 int32_t expectedFlags = 0) {
1321 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1322 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001323 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001324 }
1325
1326 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001327 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001328 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001329 expectedFlags);
1330 }
1331
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001332 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1333 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001334 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001335 expectedFlags);
1336 }
1337
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001338 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1339 int32_t expectedFlags = 0) {
1340 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001341 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001342 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001343 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1344 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1345 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1346 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1347 }
1348
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001349 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1350 ASSERT_NE(mInputReceiver, nullptr)
1351 << "Cannot consume events from a window with no receiver";
1352 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1353 }
1354
Prabir Pradhan99987712020-11-10 18:43:05 -08001355 void consumeCaptureEvent(bool hasCapture) {
1356 ASSERT_NE(mInputReceiver, nullptr)
1357 << "Cannot consume events from a window with no receiver";
1358 mInputReceiver->consumeCaptureEvent(hasCapture);
1359 }
1360
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001361 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1362 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001363 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001364 ASSERT_THAT(*motionEvent, matcher);
1365 }
1366
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001367 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001368 std::optional<int32_t> expectedDisplayId,
1369 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001370 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1371 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1372 expectedFlags);
1373 }
1374
arthurhungb89ccb02020-12-30 16:19:01 +08001375 void consumeDragEvent(bool isExiting, float x, float y) {
1376 mInputReceiver->consumeDragEvent(isExiting, x, y);
1377 }
1378
Antonio Kantekf16f2832021-09-28 04:39:20 +00001379 void consumeTouchModeEvent(bool inTouchMode) {
1380 ASSERT_NE(mInputReceiver, nullptr)
1381 << "Cannot consume events from a window with no receiver";
1382 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1383 }
1384
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001385 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001386 if (mInputReceiver == nullptr) {
1387 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1388 return std::nullopt;
1389 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001390 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001391 }
1392
1393 void finishEvent(uint32_t sequenceNum) {
1394 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1395 mInputReceiver->finishEvent(sequenceNum);
1396 }
1397
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001398 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1399 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1400 mInputReceiver->sendTimeline(inputEventId, timeline);
1401 }
1402
chaviwaf87b3e2019-10-01 16:59:28 -07001403 InputEvent* consume() {
1404 if (mInputReceiver == nullptr) {
1405 return nullptr;
1406 }
1407 return mInputReceiver->consume();
1408 }
1409
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001410 MotionEvent* consumeMotion() {
1411 InputEvent* event = consume();
1412 if (event == nullptr) {
1413 ADD_FAILURE() << "Consume failed : no event";
1414 return nullptr;
1415 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001416 if (event->getType() != InputEventType::MOTION) {
1417 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001418 return nullptr;
1419 }
1420 return static_cast<MotionEvent*>(event);
1421 }
1422
Arthur Hungb92218b2018-08-14 12:00:21 +08001423 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001424 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001425 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001426 return; // Can't receive events if the window does not have input channel
1427 }
1428 ASSERT_NE(nullptr, mInputReceiver)
1429 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001430 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001431 }
1432
chaviwaf87b3e2019-10-01 16:59:28 -07001433 sp<IBinder> getToken() { return mInfo.token; }
1434
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001435 const std::string& getName() { return mName; }
1436
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001437 void setOwnerInfo(int32_t ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001438 mInfo.ownerPid = ownerPid;
1439 mInfo.ownerUid = ownerUid;
1440 }
1441
Prabir Pradhanedd96402022-02-15 01:46:16 -08001442 int32_t getPid() const { return mInfo.ownerPid; }
1443
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001444 void destroyReceiver() { mInputReceiver = nullptr; }
1445
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001446 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1447
chaviwd1c23182019-12-20 18:44:56 -08001448private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001449 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001450 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001451 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001452 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001453 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001454};
1455
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001456std::atomic<int32_t> FakeWindowHandle::sId{1};
1457
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001458static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001459 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001460 int32_t displayId = ADISPLAY_ID_NONE,
1461 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001462 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001463 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001464 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001465 KeyEvent event;
1466 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1467
1468 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001469 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001470 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1471 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001472
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001473 if (!allowKeyRepeat) {
1474 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1475 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001476 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001477 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001478}
1479
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001480static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001481 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001482 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001483}
1484
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001485// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1486// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1487// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001488static InputEventInjectionResult injectKeyDownNoRepeat(
1489 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001490 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001491 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001492 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001493}
1494
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001495static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001496 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001497 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001498}
1499
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001500static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001501 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001502 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001503 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001504 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001505 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1506 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001507}
1508
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001509static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001510 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001511 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001512 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001513 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1514 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001515 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001516 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001517 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001518 MotionEventBuilder motionBuilder =
1519 MotionEventBuilder(action, source)
1520 .displayId(displayId)
1521 .eventTime(eventTime)
1522 .rawXCursorPosition(cursorPosition.x)
1523 .rawYCursorPosition(cursorPosition.y)
1524 .pointer(
1525 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1526 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1527 motionBuilder.downTime(eventTime);
1528 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001529
1530 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001531 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1532 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001533}
1534
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001535static InputEventInjectionResult injectMotionDown(
1536 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1537 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001538 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001539}
1540
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001541static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001542 int32_t source, int32_t displayId,
1543 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001544 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001545}
1546
Jackal Guof9696682018-10-05 12:23:23 +08001547static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1548 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1549 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001550 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001551 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1552 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001553
1554 return args;
1555}
1556
Josep del Riob3981622023-04-18 15:49:45 +00001557static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1558 int32_t displayId = ADISPLAY_ID_NONE) {
1559 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1560 // Define a valid key event.
1561 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1562 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1563 currentTime);
1564
1565 return args;
1566}
1567
1568static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1569 int32_t displayId = ADISPLAY_ID_NONE) {
1570 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1571 // Define a valid key event.
1572 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1573 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1574 AMETA_NONE, currentTime);
1575
1576 return args;
1577}
1578
Prabir Pradhan678438e2023-04-13 19:32:51 +00001579[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1580 int32_t displayId,
1581 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001582 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001583 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1584 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1585 }
1586
chaviwd1c23182019-12-20 18:44:56 -08001587 PointerProperties pointerProperties[pointerCount];
1588 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001589
chaviwd1c23182019-12-20 18:44:56 -08001590 for (size_t i = 0; i < pointerCount; i++) {
1591 pointerProperties[i].clear();
1592 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001593 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001594
chaviwd1c23182019-12-20 18:44:56 -08001595 pointerCoords[i].clear();
1596 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1597 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1598 }
Jackal Guof9696682018-10-05 12:23:23 +08001599
1600 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1601 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001602 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001603 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1604 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001605 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1606 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001607 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1608 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001609
1610 return args;
1611}
1612
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001613static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1614 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1615}
1616
chaviwd1c23182019-12-20 18:44:56 -08001617static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1618 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1619}
1620
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001621static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1622 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001623 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001624}
1625
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001626} // namespace
1627
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001628/**
1629 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1630 * broken channel.
1631 */
1632TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1633 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1634 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001635 sp<FakeWindowHandle>::make(application, mDispatcher,
1636 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001637
1638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1639
1640 // Window closes its channel, but the window remains.
1641 window->destroyReceiver();
1642 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1643}
1644
Arthur Hungb92218b2018-08-14 12:00:21 +08001645TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001647 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1648 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001649
Arthur Hung72d8dc32020-03-28 00:48:39 +00001650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1652 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001654
1655 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001656 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001657}
1658
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001659TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001661 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1662 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001663
1664 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1665 // Inject a MotionEvent to an unknown display.
1666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1667 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1669
1670 // Window should receive motion event.
1671 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1672}
1673
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001674/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001675 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001676 * This test serves as a sanity check for the next test, where setInputWindows is
1677 * called twice.
1678 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001679TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1682 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001683 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001684
1685 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1688 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001689 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690
1691 // Window should receive motion event.
1692 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1693}
1694
1695/**
1696 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697 */
1698TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001700 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1701 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001702 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703
1704 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1708 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710
1711 // Window should receive motion event.
1712 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1713}
1714
Arthur Hungb92218b2018-08-14 12:00:21 +08001715// The foreground window should receive the first touch down event.
1716TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001718 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001719 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001720 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001721 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001722
Arthur Hung72d8dc32020-03-28 00:48:39 +00001723 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1725 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001727
1728 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001729 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001730 windowSecond->assertNoEvents();
1731}
1732
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001733/**
1734 * Two windows: A top window, and a wallpaper behind the window.
1735 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1736 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001737 * 1. foregroundWindow <-- dup touch to wallpaper
1738 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001739 */
1740TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1742 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001743 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001744 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001745 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001746 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001747 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001748
1749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1751 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1752 {100, 200}))
1753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1754
1755 // Both foreground window and its wallpaper should receive the touch down
1756 foregroundWindow->consumeMotionDown();
1757 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1758
1759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1760 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1761 ADISPLAY_ID_DEFAULT, {110, 200}))
1762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1763
1764 foregroundWindow->consumeMotionMove();
1765 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1766
1767 // Now the foreground window goes away, but the wallpaper stays
1768 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1769 foregroundWindow->consumeMotionCancel();
1770 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1771 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1772}
1773
1774/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001775 * Two fingers down on the window, and lift off the first finger.
1776 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1777 * contains a single pointer.
1778 */
1779TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1781 sp<FakeWindowHandle> window =
1782 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1783
1784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001785 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1787 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1788 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001789 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001790 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1791 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1792 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1793 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001794 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001795 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1796 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1797 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1798 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001799 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1800 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1801 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1802
1803 // Remove the window. The gesture should be canceled
1804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1805 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1806 window->consumeMotionEvent(
1807 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1808}
1809
1810/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001811 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1812 * with the following differences:
1813 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1814 * clean up the connection.
1815 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1816 * Ensure that there's no crash in the dispatcher.
1817 */
1818TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1820 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001821 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001822 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001823 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001824 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001825 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826
1827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1829 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1830 {100, 200}))
1831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1832
1833 // Both foreground window and its wallpaper should receive the touch down
1834 foregroundWindow->consumeMotionDown();
1835 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1836
1837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1838 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1839 ADISPLAY_ID_DEFAULT, {110, 200}))
1840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1841
1842 foregroundWindow->consumeMotionMove();
1843 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1844
1845 // Wallpaper closes its channel, but the window remains.
1846 wallpaperWindow->destroyReceiver();
1847 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1848
1849 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1850 // is no longer valid.
1851 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1852 foregroundWindow->consumeMotionCancel();
1853}
1854
Arthur Hungc539dbb2022-12-08 07:45:36 +00001855class ShouldSplitTouchFixture : public InputDispatcherTest,
1856 public ::testing::WithParamInterface<bool> {};
1857INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1858 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001860 * A single window that receives touch (on top), and a wallpaper window underneath it.
1861 * The top window gets a multitouch gesture.
1862 * Ensure that wallpaper gets the same gesture.
1863 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001864TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001865 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001866 sp<FakeWindowHandle> foregroundWindow =
1867 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1868 foregroundWindow->setDupTouchToWallpaper(true);
1869 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870
1871 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001872 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001873 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001874
Arthur Hungc539dbb2022-12-08 07:45:36 +00001875 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876
1877 // Touch down on top window
1878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1879 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1880 {100, 100}))
1881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1882
1883 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001884 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1886
1887 // Second finger down on the top window
1888 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001889 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001891 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1892 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 .build();
1894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1895 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1896 InputEventInjectionSync::WAIT_FOR_RESULT))
1897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1898
Harry Cutts33476232023-01-30 19:57:29 +00001899 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1900 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001902
1903 const MotionEvent secondFingerUpEvent =
1904 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1905 .displayId(ADISPLAY_ID_DEFAULT)
1906 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001907 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1908 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001909 .build();
1910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1911 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1912 InputEventInjectionSync::WAIT_FOR_RESULT))
1913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1914 foregroundWindow->consumeMotionPointerUp(0);
1915 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1916
1917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001918 injectMotionEvent(mDispatcher,
1919 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1920 AINPUT_SOURCE_TOUCHSCREEN)
1921 .displayId(ADISPLAY_ID_DEFAULT)
1922 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1923 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001924 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001925 .x(100)
1926 .y(100))
1927 .build(),
1928 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1930 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1931 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001932}
1933
1934/**
1935 * Two windows: a window on the left and window on the right.
1936 * A third window, wallpaper, is behind both windows, and spans both top windows.
1937 * The first touch down goes to the left window. A second pointer touches down on the right window.
1938 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1939 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1940 * ACTION_POINTER_DOWN(1).
1941 */
1942TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1944 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001945 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001947 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948
1949 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001950 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001951 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001952 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001953
1954 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001955 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001957 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958
1959 mDispatcher->setInputWindows(
1960 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1961
1962 // Touch down on left window
1963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1964 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1965 {100, 100}))
1966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1967
1968 // Both foreground window and its wallpaper should receive the touch down
1969 leftWindow->consumeMotionDown();
1970 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1971
1972 // Second finger down on the right window
1973 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001974 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001975 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001976 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1977 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978 .build();
1979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1980 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1981 InputEventInjectionSync::WAIT_FOR_RESULT))
1982 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1983
1984 leftWindow->consumeMotionMove();
1985 // Since the touch is split, right window gets ACTION_DOWN
1986 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001987 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 expectedWallpaperFlags);
1989
1990 // Now, leftWindow, which received the first finger, disappears.
1991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1992 leftWindow->consumeMotionCancel();
1993 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1994 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1995
1996 // The pointer that's still down on the right window moves, and goes to the right window only.
1997 // As far as the dispatcher's concerned though, both pointers are still present.
1998 const MotionEvent secondFingerMoveEvent =
1999 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2000 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002001 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2002 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003 .build();
2004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2005 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2006 InputEventInjectionSync::WAIT_FOR_RESULT));
2007 rightWindow->consumeMotionMove();
2008
2009 leftWindow->assertNoEvents();
2010 rightWindow->assertNoEvents();
2011 wallpaperWindow->assertNoEvents();
2012}
2013
Arthur Hungc539dbb2022-12-08 07:45:36 +00002014/**
2015 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2016 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2017 * The right window should receive ACTION_DOWN.
2018 */
2019TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002021 sp<FakeWindowHandle> leftWindow =
2022 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2023 leftWindow->setFrame(Rect(0, 0, 200, 200));
2024 leftWindow->setDupTouchToWallpaper(true);
2025 leftWindow->setSlippery(true);
2026
2027 sp<FakeWindowHandle> rightWindow =
2028 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2029 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002030
2031 sp<FakeWindowHandle> wallpaperWindow =
2032 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2033 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002034
Arthur Hungc539dbb2022-12-08 07:45:36 +00002035 mDispatcher->setInputWindows(
2036 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002037
Arthur Hungc539dbb2022-12-08 07:45:36 +00002038 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2040 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043
2044 // Both foreground window and its wallpaper should receive the touch down
2045 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002046 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2047
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2051 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2053
Arthur Hungc539dbb2022-12-08 07:45:36 +00002054 leftWindow->consumeMotionCancel();
2055 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2056 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002057}
2058
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002059/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002060 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2061 * interactive, it might stop sending this flag.
2062 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2063 * to have a consistent input stream.
2064 *
2065 * Test procedure:
2066 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2067 * DOWN (new gesture).
2068 *
2069 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2070 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2071 *
2072 * We technically just need a single window here, but we are using two windows (spy on top and a
2073 * regular window below) to emulate the actual situation where it happens on the device.
2074 */
2075TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2077 sp<FakeWindowHandle> spyWindow =
2078 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2079 spyWindow->setFrame(Rect(0, 0, 200, 200));
2080 spyWindow->setTrustedOverlay(true);
2081 spyWindow->setSpy(true);
2082
2083 sp<FakeWindowHandle> window =
2084 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2085 window->setFrame(Rect(0, 0, 200, 200));
2086
2087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2088 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002089
2090 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002091 mDispatcher->notifyMotion(
2092 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2093 .deviceId(touchDeviceId)
2094 .policyFlags(DEFAULT_POLICY_FLAGS)
2095 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2096 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002097
Prabir Pradhan678438e2023-04-13 19:32:51 +00002098 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2099 .deviceId(touchDeviceId)
2100 .policyFlags(DEFAULT_POLICY_FLAGS)
2101 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2102 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2103 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002104 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2105 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2106 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2107 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2108
2109 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002110 mDispatcher->notifyMotion(
2111 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2112 .deviceId(touchDeviceId)
2113 .policyFlags(0)
2114 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2115 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2116 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002117 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2118 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2119
2120 // We don't need to reset the device to reproduce the issue, but the reset event typically
2121 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002122 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002123
2124 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002125 mDispatcher->notifyMotion(
2126 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2127 .deviceId(touchDeviceId)
2128 .policyFlags(DEFAULT_POLICY_FLAGS)
2129 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2130 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002131 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2132 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2133
2134 // No more events
2135 spyWindow->assertNoEvents();
2136 window->assertNoEvents();
2137}
2138
2139/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002140 * Two windows: a window on the left and a window on the right.
2141 * Mouse is hovered from the right window into the left window.
2142 * Next, we tap on the left window, where the cursor was last seen.
2143 * The second tap is done onto the right window.
2144 * The mouse and tap are from two different devices.
2145 * We technically don't need to set the downtime / eventtime for these events, but setting these
2146 * explicitly helps during debugging.
2147 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2148 * In the buggy implementation, a tap on the right window would cause a crash.
2149 */
2150TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2152 sp<FakeWindowHandle> leftWindow =
2153 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2154 leftWindow->setFrame(Rect(0, 0, 200, 200));
2155
2156 sp<FakeWindowHandle> rightWindow =
2157 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2158 rightWindow->setFrame(Rect(200, 0, 400, 200));
2159
2160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2161 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2162 // stale.
2163 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2164 const int32_t mouseDeviceId = 6;
2165 const int32_t touchDeviceId = 4;
2166 // Move the cursor from right
2167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2168 injectMotionEvent(mDispatcher,
2169 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2170 AINPUT_SOURCE_MOUSE)
2171 .deviceId(mouseDeviceId)
2172 .downTime(baseTime + 10)
2173 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002174 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002175 .x(300)
2176 .y(100))
2177 .build()));
2178 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2179
2180 // .. to the left window
2181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2182 injectMotionEvent(mDispatcher,
2183 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2184 AINPUT_SOURCE_MOUSE)
2185 .deviceId(mouseDeviceId)
2186 .downTime(baseTime + 10)
2187 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002188 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002189 .x(110)
2190 .y(100))
2191 .build()));
2192 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2193 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2194 // Now tap the left window
2195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2196 injectMotionEvent(mDispatcher,
2197 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2198 AINPUT_SOURCE_TOUCHSCREEN)
2199 .deviceId(touchDeviceId)
2200 .downTime(baseTime + 40)
2201 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002202 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002203 .x(100)
2204 .y(100))
2205 .build()));
2206 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2207 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2208
2209 // release tap
2210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2211 injectMotionEvent(mDispatcher,
2212 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2213 AINPUT_SOURCE_TOUCHSCREEN)
2214 .deviceId(touchDeviceId)
2215 .downTime(baseTime + 40)
2216 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002217 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002218 .x(100)
2219 .y(100))
2220 .build()));
2221 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2222
2223 // Tap the window on the right
2224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2225 injectMotionEvent(mDispatcher,
2226 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2227 AINPUT_SOURCE_TOUCHSCREEN)
2228 .deviceId(touchDeviceId)
2229 .downTime(baseTime + 60)
2230 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002231 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002232 .x(300)
2233 .y(100))
2234 .build()));
2235 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2236
2237 // release tap
2238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2239 injectMotionEvent(mDispatcher,
2240 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2241 AINPUT_SOURCE_TOUCHSCREEN)
2242 .deviceId(touchDeviceId)
2243 .downTime(baseTime + 60)
2244 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002245 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002246 .x(300)
2247 .y(100))
2248 .build()));
2249 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2250
2251 // No more events
2252 leftWindow->assertNoEvents();
2253 rightWindow->assertNoEvents();
2254}
2255
2256/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002257 * Start hovering in a window. While this hover is still active, make another window appear on top.
2258 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2259 * While the top window is present, the hovering is stopped.
2260 * Later, hovering gets resumed again.
2261 * Ensure that new hover gesture is handled correctly.
2262 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2263 * to the window that's currently being hovered over.
2264 */
2265TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2267 sp<FakeWindowHandle> window =
2268 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2269 window->setFrame(Rect(0, 0, 200, 200));
2270
2271 // Only a single window is present at first
2272 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2273
2274 // Start hovering in the window
2275 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2276 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2277 .build());
2278 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2279
2280 // Now, an obscuring window appears!
2281 sp<FakeWindowHandle> obscuringWindow =
2282 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2283 ADISPLAY_ID_DEFAULT,
2284 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2285 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2286 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2287 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2288 obscuringWindow->setNoInputChannel(true);
2289 obscuringWindow->setFocusable(false);
2290 obscuringWindow->setAlpha(1.0);
2291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2292
2293 // While this new obscuring window is present, the hovering is stopped
2294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2295 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2296 .build());
2297 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2298
2299 // Now the obscuring window goes away.
2300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2301
2302 // And a new hover gesture starts.
2303 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2304 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2305 .build());
2306 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2307}
2308
2309/**
2310 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2311 * the obscuring window.
2312 */
2313TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2315 sp<FakeWindowHandle> window =
2316 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2317 window->setFrame(Rect(0, 0, 200, 200));
2318
2319 // Only a single window is present at first
2320 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2321
2322 // Start hovering in the window
2323 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2324 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2325 .build());
2326 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2327
2328 // Now, an obscuring window appears!
2329 sp<FakeWindowHandle> obscuringWindow =
2330 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2331 ADISPLAY_ID_DEFAULT,
2332 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2333 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2334 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2335 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2336 obscuringWindow->setNoInputChannel(true);
2337 obscuringWindow->setFocusable(false);
2338 obscuringWindow->setAlpha(1.0);
2339 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2340
2341 // While this new obscuring window is present, the hovering continues. The event can't go to the
2342 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2343 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2344 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2345 .build());
2346 obscuringWindow->assertNoEvents();
2347 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2348
2349 // Now the obscuring window goes away.
2350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2351
2352 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2353 // so it should generate a HOVER_ENTER
2354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2355 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2356 .build());
2357 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2358
2359 // Now the MOVE should be getting dispatched normally
2360 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2361 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2362 .build());
2363 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2364}
2365
2366/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002367 * Two windows: a window on the left and a window on the right.
2368 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2369 * down. Then, on the left window, also place second touch pointer down.
2370 * This test tries to reproduce a crash.
2371 * In the buggy implementation, second pointer down on the left window would cause a crash.
2372 */
2373TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2375 sp<FakeWindowHandle> leftWindow =
2376 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2377 leftWindow->setFrame(Rect(0, 0, 200, 200));
2378
2379 sp<FakeWindowHandle> rightWindow =
2380 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2381 rightWindow->setFrame(Rect(200, 0, 400, 200));
2382
2383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2384
2385 const int32_t touchDeviceId = 4;
2386 const int32_t mouseDeviceId = 6;
2387 NotifyMotionArgs args;
2388
2389 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2391 .deviceId(mouseDeviceId)
2392 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2393 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002394 leftWindow->consumeMotionEvent(
2395 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2396
2397 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002398 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2399 .deviceId(mouseDeviceId)
2400 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2401 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2402 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002403
2404 leftWindow->consumeMotionEvent(
2405 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2406 leftWindow->consumeMotionEvent(
2407 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2408
Prabir Pradhan678438e2023-04-13 19:32:51 +00002409 mDispatcher->notifyMotion(
2410 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2411 .deviceId(mouseDeviceId)
2412 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2413 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2414 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2415 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002416 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2417
2418 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2420 .deviceId(touchDeviceId)
2421 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2422 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002423 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2424
2425 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2426
2427 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002428 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2429 .deviceId(touchDeviceId)
2430 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2431 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2432 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002433 leftWindow->consumeMotionEvent(
2434 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2435 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2436 // current implementation.
2437 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2438 rightWindow->consumeMotionEvent(
2439 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2440
2441 leftWindow->assertNoEvents();
2442 rightWindow->assertNoEvents();
2443}
2444
2445/**
2446 * On a single window, use two different devices: mouse and touch.
2447 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2448 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2449 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2450 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2451 * represent a new gesture.
2452 */
2453TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2455 sp<FakeWindowHandle> window =
2456 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2457 window->setFrame(Rect(0, 0, 400, 400));
2458
2459 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2460
2461 const int32_t touchDeviceId = 4;
2462 const int32_t mouseDeviceId = 6;
2463 NotifyMotionArgs args;
2464
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002465 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2467 .deviceId(touchDeviceId)
2468 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2469 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002470 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002471 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2472 .deviceId(touchDeviceId)
2473 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2474 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2475 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002476 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002477 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2478 .deviceId(touchDeviceId)
2479 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2480 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002482 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2483 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2484 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2485
2486 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2488 .deviceId(mouseDeviceId)
2489 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2490 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2491 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002492
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002494 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002495 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2496
Prabir Pradhan678438e2023-04-13 19:32:51 +00002497 mDispatcher->notifyMotion(
2498 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2499 .deviceId(mouseDeviceId)
2500 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2501 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2502 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2503 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002504 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2505
2506 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002507 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2508 .deviceId(touchDeviceId)
2509 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2510 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2511 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002512 // The pointer_down event should be ignored
2513 window->assertNoEvents();
2514}
2515
2516/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002517 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2518 * the injected event.
2519 */
2520TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2521 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2522 sp<FakeWindowHandle> window =
2523 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2524 window->setFrame(Rect(0, 0, 400, 400));
2525
2526 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2527
2528 const int32_t touchDeviceId = 4;
2529 NotifyMotionArgs args;
2530 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2531 // completion.
2532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2533 injectMotionEvent(mDispatcher,
2534 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2535 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002536 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002537 .x(50)
2538 .y(50))
2539 .build()));
2540 window->consumeMotionEvent(
2541 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2542
2543 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2544 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2546 .deviceId(touchDeviceId)
2547 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2548 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002549
2550 window->consumeMotionEvent(
2551 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2552 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2553}
2554
2555/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002556 * This test is similar to the test above, but the sequence of injected events is different.
2557 *
2558 * Two windows: a window on the left and a window on the right.
2559 * Mouse is hovered over the left window.
2560 * Next, we tap on the left window, where the cursor was last seen.
2561 *
2562 * After that, we inject one finger down onto the right window, and then a second finger down onto
2563 * the left window.
2564 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2565 * window (first), and then another on the left window (second).
2566 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2567 * In the buggy implementation, second finger down on the left window would cause a crash.
2568 */
2569TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2571 sp<FakeWindowHandle> leftWindow =
2572 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2573 leftWindow->setFrame(Rect(0, 0, 200, 200));
2574
2575 sp<FakeWindowHandle> rightWindow =
2576 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2577 rightWindow->setFrame(Rect(200, 0, 400, 200));
2578
2579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2580
2581 const int32_t mouseDeviceId = 6;
2582 const int32_t touchDeviceId = 4;
2583 // Hover over the left window. Keep the cursor there.
2584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2585 injectMotionEvent(mDispatcher,
2586 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2587 AINPUT_SOURCE_MOUSE)
2588 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002589 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002590 .x(50)
2591 .y(50))
2592 .build()));
2593 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2594
2595 // Tap on left window
2596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2597 injectMotionEvent(mDispatcher,
2598 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2599 AINPUT_SOURCE_TOUCHSCREEN)
2600 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002601 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002602 .x(100)
2603 .y(100))
2604 .build()));
2605
2606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2607 injectMotionEvent(mDispatcher,
2608 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2609 AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002611 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002612 .x(100)
2613 .y(100))
2614 .build()));
2615 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2616 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2617 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2618
2619 // First finger down on right window
2620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2621 injectMotionEvent(mDispatcher,
2622 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2623 AINPUT_SOURCE_TOUCHSCREEN)
2624 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002625 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002626 .x(300)
2627 .y(100))
2628 .build()));
2629 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2630
2631 // Second finger down on the left window
2632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2633 injectMotionEvent(mDispatcher,
2634 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2635 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002636 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002637 .x(300)
2638 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002639 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002640 .x(100)
2641 .y(100))
2642 .build()));
2643 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2644 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2645
2646 // No more events
2647 leftWindow->assertNoEvents();
2648 rightWindow->assertNoEvents();
2649}
2650
2651/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002652 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2653 * While the touch is down, new hover events from the stylus device should be ignored. After the
2654 * touch is gone, stylus hovering should start working again.
2655 */
2656TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2658 sp<FakeWindowHandle> window =
2659 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2660 window->setFrame(Rect(0, 0, 200, 200));
2661
2662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2663
2664 const int32_t stylusDeviceId = 5;
2665 const int32_t touchDeviceId = 4;
2666 // Start hovering with stylus
2667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2668 injectMotionEvent(mDispatcher,
2669 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2670 AINPUT_SOURCE_STYLUS)
2671 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002672 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002673 .x(50)
2674 .y(50))
2675 .build()));
2676 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2677
2678 // Finger down on the window
2679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2680 injectMotionEvent(mDispatcher,
2681 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2682 AINPUT_SOURCE_TOUCHSCREEN)
2683 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002684 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002685 .x(100)
2686 .y(100))
2687 .build()));
2688 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2689 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2690
2691 // Try to continue hovering with stylus. Since we are already down, injection should fail
2692 ASSERT_EQ(InputEventInjectionResult::FAILED,
2693 injectMotionEvent(mDispatcher,
2694 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2695 AINPUT_SOURCE_STYLUS)
2696 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002697 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002698 .x(50)
2699 .y(50))
2700 .build()));
2701 // No event should be sent. This event should be ignored because a pointer from another device
2702 // is already down.
2703
2704 // Lift up the finger
2705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2706 injectMotionEvent(mDispatcher,
2707 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2708 AINPUT_SOURCE_TOUCHSCREEN)
2709 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002710 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002711 .x(100)
2712 .y(100))
2713 .build()));
2714 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2715
2716 // Now that the touch is gone, stylus hovering should start working again
2717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2718 injectMotionEvent(mDispatcher,
2719 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2720 AINPUT_SOURCE_STYLUS)
2721 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002722 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002723 .x(50)
2724 .y(50))
2725 .build()));
2726 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2727 // No more events
2728 window->assertNoEvents();
2729}
2730
2731/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002732 * A spy window above a window with no input channel.
2733 * Start hovering with a stylus device, and then tap with it.
2734 * Ensure spy window receives the entire sequence.
2735 */
2736TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2738 sp<FakeWindowHandle> spyWindow =
2739 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2740 spyWindow->setFrame(Rect(0, 0, 200, 200));
2741 spyWindow->setTrustedOverlay(true);
2742 spyWindow->setSpy(true);
2743 sp<FakeWindowHandle> window =
2744 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2745 window->setNoInputChannel(true);
2746 window->setFrame(Rect(0, 0, 200, 200));
2747
2748 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2749
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002750 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002751 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2753 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002754 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2755 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2757 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2758 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002759 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2760
2761 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2763 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2764 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002765 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2766
2767 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2769 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2770 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002771 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2772
2773 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2776 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002777 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2778 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2780 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2781 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002782 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2783
2784 // No more events
2785 spyWindow->assertNoEvents();
2786 window->assertNoEvents();
2787}
2788
2789/**
2790 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2791 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2792 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2793 * While the mouse is down, new move events from the touch device should be ignored.
2794 */
2795TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2797 sp<FakeWindowHandle> spyWindow =
2798 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2799 spyWindow->setFrame(Rect(0, 0, 200, 200));
2800 spyWindow->setTrustedOverlay(true);
2801 spyWindow->setSpy(true);
2802 sp<FakeWindowHandle> window =
2803 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2804 window->setFrame(Rect(0, 0, 200, 200));
2805
2806 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2807
2808 const int32_t mouseDeviceId = 7;
2809 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002810
2811 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2813 .deviceId(mouseDeviceId)
2814 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2815 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002816 spyWindow->consumeMotionEvent(
2817 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2818 window->consumeMotionEvent(
2819 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2820
2821 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2823 .deviceId(touchDeviceId)
2824 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2825 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002826 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2827 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2828 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2829 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2830
Prabir Pradhan678438e2023-04-13 19:32:51 +00002831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2832 .deviceId(touchDeviceId)
2833 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2834 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002835 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2836 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2837
2838 // Pilfer the stream
2839 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2840 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2841
Prabir Pradhan678438e2023-04-13 19:32:51 +00002842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2843 .deviceId(touchDeviceId)
2844 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2845 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002846 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2847
2848 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2850 .deviceId(mouseDeviceId)
2851 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2853 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002854
2855 spyWindow->consumeMotionEvent(
2856 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2857 spyWindow->consumeMotionEvent(
2858 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2859 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2860
Prabir Pradhan678438e2023-04-13 19:32:51 +00002861 mDispatcher->notifyMotion(
2862 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2863 .deviceId(mouseDeviceId)
2864 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2865 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2866 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2867 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002868 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2869 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2870
2871 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2873 .deviceId(mouseDeviceId)
2874 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2875 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2876 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002877 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2878 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2879
2880 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2882 .deviceId(touchDeviceId)
2883 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2884 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002885
2886 // No more events
2887 spyWindow->assertNoEvents();
2888 window->assertNoEvents();
2889}
2890
2891/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002892 * On the display, have a single window, and also an area where there's no window.
2893 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2894 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2895 */
2896TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2897 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2898 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002899 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002900
2901 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002902
2903 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002904 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002905
2906 mDispatcher->waitForIdle();
2907 window->assertNoEvents();
2908
2909 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002910 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002911 mDispatcher->waitForIdle();
2912 window->consumeMotionDown();
2913}
2914
2915/**
2916 * Same test as above, but instead of touching the empty space, the first touch goes to
2917 * non-touchable window.
2918 */
2919TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2920 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2921 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002922 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002923 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2924 window1->setTouchable(false);
2925 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002926 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002927 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2928
2929 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2930
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002931 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002932 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002933
2934 mDispatcher->waitForIdle();
2935 window1->assertNoEvents();
2936 window2->assertNoEvents();
2937
2938 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002939 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002940 mDispatcher->waitForIdle();
2941 window2->consumeMotionDown();
2942}
2943
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002944/**
2945 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2946 * to the event time of the first ACTION_DOWN sent to the particular window.
2947 */
2948TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2950 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002951 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002952 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2953 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002954 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002955 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2956
2957 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2958
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002959 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002960 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002961
2962 mDispatcher->waitForIdle();
2963 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002964 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 window2->assertNoEvents();
2966 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2967 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2968 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2969
2970 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002971 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002972 mDispatcher->waitForIdle();
2973 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002974 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002975 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2976 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2977 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2978 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2979
2980 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002981 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002982 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002983 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002984
2985 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002986 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002987 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002988 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002989
2990 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2991 window1->consumeMotionMove();
2992 window1->assertNoEvents();
2993
2994 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002995 mDispatcher->notifyMotion(
2996 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002997 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002998 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002999
Prabir Pradhan678438e2023-04-13 19:32:51 +00003000 mDispatcher->notifyMotion(
3001 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003002 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003003 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003004}
3005
Garfield Tandf26e862020-07-01 20:18:19 -07003006TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003008 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003009 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003010 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003011 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003012 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003013 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003014
3015 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3016
3017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3018
3019 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003021 injectMotionEvent(mDispatcher,
3022 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3023 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003024 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003025 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003026 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003027
3028 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003030 injectMotionEvent(mDispatcher,
3031 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3032 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003034 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003035 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3036 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003037
3038 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003040 injectMotionEvent(mDispatcher,
3041 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3042 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003043 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003044 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003045 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3046 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003047
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003049 injectMotionEvent(mDispatcher,
3050 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3051 AINPUT_SOURCE_MOUSE)
3052 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3053 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003055 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003056 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003057
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003059 injectMotionEvent(mDispatcher,
3060 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3061 AINPUT_SOURCE_MOUSE)
3062 .buttonState(0)
3063 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003064 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003065 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003066 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003067
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003069 injectMotionEvent(mDispatcher,
3070 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3071 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003072 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003073 .build()));
3074 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3075
3076 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003078 injectMotionEvent(mDispatcher,
3079 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3080 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003081 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003082 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003083 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003084
3085 // No more events
3086 windowLeft->assertNoEvents();
3087 windowRight->assertNoEvents();
3088}
3089
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003090/**
3091 * Put two fingers down (and don't release them) and click the mouse button.
3092 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3093 * currently active gesture should be canceled, and the new one should proceed.
3094 */
3095TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3097 sp<FakeWindowHandle> window =
3098 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3099 window->setFrame(Rect(0, 0, 600, 800));
3100
3101 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3102
3103 const int32_t touchDeviceId = 4;
3104 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003105
3106 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3110 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003111
Prabir Pradhan678438e2023-04-13 19:32:51 +00003112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3113 .deviceId(touchDeviceId)
3114 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3115 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3116 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003117 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3118 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3119
3120 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3122 .deviceId(mouseDeviceId)
3123 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3124 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3125 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003126 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3127 WithPointerCount(2u)));
3128 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3129
Prabir Pradhan678438e2023-04-13 19:32:51 +00003130 mDispatcher->notifyMotion(
3131 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3132 .deviceId(mouseDeviceId)
3133 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3134 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3135 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3136 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003137 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3138
3139 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3140 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3142 .deviceId(touchDeviceId)
3143 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3144 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3145 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003146 window->assertNoEvents();
3147}
3148
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003149TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3151
3152 sp<FakeWindowHandle> spyWindow =
3153 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3154 spyWindow->setFrame(Rect(0, 0, 600, 800));
3155 spyWindow->setTrustedOverlay(true);
3156 spyWindow->setSpy(true);
3157 sp<FakeWindowHandle> window =
3158 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3159 window->setFrame(Rect(0, 0, 600, 800));
3160
3161 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3163
3164 // Send mouse cursor to the window
3165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3166 injectMotionEvent(mDispatcher,
3167 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3168 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003169 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003170 .x(100)
3171 .y(100))
3172 .build()));
3173
3174 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3175 WithSource(AINPUT_SOURCE_MOUSE)));
3176 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3177 WithSource(AINPUT_SOURCE_MOUSE)));
3178
3179 window->assertNoEvents();
3180 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003181}
3182
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003183TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3184 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3185
3186 sp<FakeWindowHandle> spyWindow =
3187 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3188 spyWindow->setFrame(Rect(0, 0, 600, 800));
3189 spyWindow->setTrustedOverlay(true);
3190 spyWindow->setSpy(true);
3191 sp<FakeWindowHandle> window =
3192 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3193 window->setFrame(Rect(0, 0, 600, 800));
3194
3195 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3196 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3197
3198 // Send mouse cursor to the window
3199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3200 injectMotionEvent(mDispatcher,
3201 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3202 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003203 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003204 .x(100)
3205 .y(100))
3206 .build()));
3207
3208 // Move mouse cursor
3209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3210 injectMotionEvent(mDispatcher,
3211 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3212 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003213 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003214 .x(110)
3215 .y(110))
3216 .build()));
3217
3218 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3219 WithSource(AINPUT_SOURCE_MOUSE)));
3220 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3221 WithSource(AINPUT_SOURCE_MOUSE)));
3222 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3223 WithSource(AINPUT_SOURCE_MOUSE)));
3224 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3225 WithSource(AINPUT_SOURCE_MOUSE)));
3226 // Touch down on the window
3227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3228 injectMotionEvent(mDispatcher,
3229 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3230 AINPUT_SOURCE_TOUCHSCREEN)
3231 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003232 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003233 .x(200)
3234 .y(200))
3235 .build()));
3236 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3237 WithSource(AINPUT_SOURCE_MOUSE)));
3238 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3239 WithSource(AINPUT_SOURCE_MOUSE)));
3240 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3241 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3242 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3243 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3244
3245 // pilfer the motion, retaining the gesture on the spy window.
3246 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3247 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3248 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3249
3250 // Touch UP on the window
3251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3252 injectMotionEvent(mDispatcher,
3253 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3254 AINPUT_SOURCE_TOUCHSCREEN)
3255 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003256 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003257 .x(200)
3258 .y(200))
3259 .build()));
3260 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3261 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3262
3263 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3264 // to send a new gesture. It should again go to both windows (spy and the window below), just
3265 // like the first gesture did, before pilfering. The window configuration has not changed.
3266
3267 // One more tap - DOWN
3268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3269 injectMotionEvent(mDispatcher,
3270 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3271 AINPUT_SOURCE_TOUCHSCREEN)
3272 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003273 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003274 .x(250)
3275 .y(250))
3276 .build()));
3277 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3278 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3279 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3280 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3281
3282 // Touch UP on the window
3283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3284 injectMotionEvent(mDispatcher,
3285 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3286 AINPUT_SOURCE_TOUCHSCREEN)
3287 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003288 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003289 .x(250)
3290 .y(250))
3291 .build()));
3292 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3293 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3294 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3295 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3296
3297 window->assertNoEvents();
3298 spyWindow->assertNoEvents();
3299}
3300
Garfield Tandf26e862020-07-01 20:18:19 -07003301// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3302// directly in this test.
3303TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003305 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003306 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003307 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003308
3309 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3310
3311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3312
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003314 injectMotionEvent(mDispatcher,
3315 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3316 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003317 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003318 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003319 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003320 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003322 injectMotionEvent(mDispatcher,
3323 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3324 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003325 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003326 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003327 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3328 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003329
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003331 injectMotionEvent(mDispatcher,
3332 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3333 AINPUT_SOURCE_MOUSE)
3334 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3335 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003336 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003337 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003338 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003341 injectMotionEvent(mDispatcher,
3342 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3343 AINPUT_SOURCE_MOUSE)
3344 .buttonState(0)
3345 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003346 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003347 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003348 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003349
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003351 injectMotionEvent(mDispatcher,
3352 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3353 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003354 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003355 .build()));
3356 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3357
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003358 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3359 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3360 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003361 injectMotionEvent(mDispatcher,
3362 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3363 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003364 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003365 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003366 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003367}
3368
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003369/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003370 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3371 * is generated.
3372 */
3373TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3375 sp<FakeWindowHandle> window =
3376 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3377 window->setFrame(Rect(0, 0, 1200, 800));
3378
3379 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3380
3381 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3382
3383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3384 injectMotionEvent(mDispatcher,
3385 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3386 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003387 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003388 .x(300)
3389 .y(400))
3390 .build()));
3391 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3392
3393 // Remove the window, but keep the channel.
3394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3395 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3396}
3397
3398/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003399 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3400 */
3401TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3402 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3403 sp<FakeWindowHandle> window =
3404 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3405 window->setFrame(Rect(0, 0, 100, 100));
3406
3407 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3408
3409 const int32_t mouseDeviceId = 7;
3410 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003411
3412 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3414 .deviceId(mouseDeviceId)
3415 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3416 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003417 window->consumeMotionEvent(
3418 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3419
3420 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3422 .deviceId(touchDeviceId)
3423 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3424 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003425
3426 window->consumeMotionEvent(
3427 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3428 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3429}
3430
3431/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003432 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003433 * The tap causes a HOVER_EXIT event to be generated because the current event
3434 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003435 */
3436TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3437 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3438 sp<FakeWindowHandle> window =
3439 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3440 window->setFrame(Rect(0, 0, 100, 100));
3441
3442 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3443
3444 // Inject a hover_move from mouse.
3445 NotifyMotionArgs motionArgs =
3446 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3447 ADISPLAY_ID_DEFAULT, {{50, 50}});
3448 motionArgs.xCursorPosition = 50;
3449 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003450 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003451 ASSERT_NO_FATAL_FAILURE(
3452 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3453 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003454
3455 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003456 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3457 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3458 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003459 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003460 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3461 WithSource(AINPUT_SOURCE_MOUSE))));
3462
3463 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003464 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3465 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3466
Prabir Pradhan678438e2023-04-13 19:32:51 +00003467 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3468 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003469 ASSERT_NO_FATAL_FAILURE(
3470 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3471 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3472}
3473
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003474TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3475 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3476 sp<FakeWindowHandle> windowDefaultDisplay =
3477 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3478 ADISPLAY_ID_DEFAULT);
3479 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3480 sp<FakeWindowHandle> windowSecondDisplay =
3481 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3482 SECOND_DISPLAY_ID);
3483 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3484
3485 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3486 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3487
3488 // Set cursor position in window in default display and check that hover enter and move
3489 // events are generated.
3490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3491 injectMotionEvent(mDispatcher,
3492 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3493 AINPUT_SOURCE_MOUSE)
3494 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003495 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003496 .x(300)
3497 .y(600))
3498 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003499 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003500
3501 // Remove all windows in secondary display and check that no event happens on window in
3502 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003503 mDispatcher->setInputWindows(
3504 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003505 windowDefaultDisplay->assertNoEvents();
3506
3507 // Move cursor position in window in default display and check that only hover move
3508 // event is generated and not hover enter event.
3509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3510 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3512 injectMotionEvent(mDispatcher,
3513 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3514 AINPUT_SOURCE_MOUSE)
3515 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003516 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003517 .x(400)
3518 .y(700))
3519 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003520 windowDefaultDisplay->consumeMotionEvent(
3521 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3522 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003523 windowDefaultDisplay->assertNoEvents();
3524}
3525
Garfield Tan00f511d2019-06-12 16:55:40 -07003526TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003528
3529 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003530 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003531 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003532 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003533 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003534 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003535
3536 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3537
Arthur Hung72d8dc32020-03-28 00:48:39 +00003538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003539
3540 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3541 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003543 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003544 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003545 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003546 windowRight->assertNoEvents();
3547}
3548
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003549TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003551 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3552 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003553 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003554
Arthur Hung72d8dc32020-03-28 00:48:39 +00003555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003556 setFocusedWindow(window);
3557
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003558 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003559
Prabir Pradhan678438e2023-04-13 19:32:51 +00003560 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003561
3562 // Window should receive key down event.
3563 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3564
3565 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3566 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003567 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003568 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003569 AKEY_EVENT_FLAG_CANCELED);
3570}
3571
3572TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003573 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003574 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3575 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003576
Arthur Hung72d8dc32020-03-28 00:48:39 +00003577 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003578
Prabir Pradhan678438e2023-04-13 19:32:51 +00003579 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3580 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003581
3582 // Window should receive motion down event.
3583 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3584
3585 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3586 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003587 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003588 window->consumeMotionEvent(
3589 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003590}
3591
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003592TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3594 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3595 "Fake Window", ADISPLAY_ID_DEFAULT);
3596
3597 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3598
3599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3600 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3601 .build());
3602
3603 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3604
3605 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3606 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3607 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3608
3609 // After the device has been reset, a new hovering stream can be sent to the window
3610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3611 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3612 .build());
3613 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3614}
3615
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003616TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3617 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003618 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3619 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003620 window->setFocusable(true);
3621
3622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3623 setFocusedWindow(window);
3624
3625 window->consumeFocusEvent(true);
3626
Prabir Pradhan678438e2023-04-13 19:32:51 +00003627 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003628 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3629 const nsecs_t injectTime = keyArgs.eventTime;
3630 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003631 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003632 // The dispatching time should be always greater than or equal to intercept key timeout.
3633 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3634 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3635 std::chrono::nanoseconds(interceptKeyTimeout).count());
3636}
3637
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003638/**
3639 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3640 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003641TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003643 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3644 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003645 window->setFocusable(true);
3646
3647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3648 setFocusedWindow(window);
3649
3650 window->consumeFocusEvent(true);
3651
Prabir Pradhan678438e2023-04-13 19:32:51 +00003652 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003653 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003654
3655 // Set a value that's significantly larger than the default consumption timeout. If the
3656 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3657 mFakePolicy->setInterceptKeyTimeout(600ms);
3658 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3659 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003660 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3661}
3662
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003663/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003664 * Two windows. First is a regular window. Second does not overlap with the first, and has
3665 * WATCH_OUTSIDE_TOUCH.
3666 * Both windows are owned by the same UID.
3667 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3668 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3669 */
3670TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3672 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3673 "First Window", ADISPLAY_ID_DEFAULT);
3674 window->setFrame(Rect{0, 0, 100, 100});
3675
3676 sp<FakeWindowHandle> outsideWindow =
3677 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3678 ADISPLAY_ID_DEFAULT);
3679 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3680 outsideWindow->setWatchOutsideTouch(true);
3681 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3682 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3683
3684 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003685 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3686 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3687 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003688 window->consumeMotionDown();
3689 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3690 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3691 outsideWindow->consumeMotionEvent(
3692 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3693}
3694
3695/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003696 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3697 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3698 * ACTION_OUTSIDE event is sent per gesture.
3699 */
3700TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3701 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3704 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003705 window->setWatchOutsideTouch(true);
3706 window->setFrame(Rect{0, 0, 100, 100});
3707 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003708 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3709 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003710 secondWindow->setFrame(Rect{100, 100, 200, 200});
3711 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003712 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3713 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003714 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3716
3717 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003718 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3719 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3720 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003721 window->assertNoEvents();
3722 secondWindow->assertNoEvents();
3723
3724 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3725 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003726 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3727 ADISPLAY_ID_DEFAULT,
3728 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003729 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3730 window->consumeMotionEvent(
3731 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003732 secondWindow->consumeMotionDown();
3733 thirdWindow->assertNoEvents();
3734
3735 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3736 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003737 mDispatcher->notifyMotion(
3738 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3739 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003740 window->assertNoEvents();
3741 secondWindow->consumeMotionMove();
3742 thirdWindow->consumeMotionDown();
3743}
3744
Prabir Pradhan814fe082022-07-22 20:22:18 +00003745TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003747 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3748 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003749 window->setFocusable(true);
3750
Patrick Williamsd828f302023-04-28 17:52:08 -05003751 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003752 setFocusedWindow(window);
3753
3754 window->consumeFocusEvent(true);
3755
Prabir Pradhan678438e2023-04-13 19:32:51 +00003756 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3757 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3758 mDispatcher->notifyKey(keyDown);
3759 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003760
3761 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3762 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3763
3764 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003765 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003766
3767 window->consumeFocusEvent(false);
3768
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyKey(keyDown);
3770 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003771 window->assertNoEvents();
3772}
3773
Arthur Hung96483742022-11-15 03:30:48 +00003774TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3776 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3777 "Fake Window", ADISPLAY_ID_DEFAULT);
3778 // Ensure window is non-split and have some transform.
3779 window->setPreventSplitting(true);
3780 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003781 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003782
3783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3784 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3785 {50, 50}))
3786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3787 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3788
3789 const MotionEvent secondFingerDownEvent =
3790 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3791 .displayId(ADISPLAY_ID_DEFAULT)
3792 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003793 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3794 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003795 .build();
3796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3797 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3798 InputEventInjectionSync::WAIT_FOR_RESULT))
3799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3800
3801 const MotionEvent* event = window->consumeMotion();
3802 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3803 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3804 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3805 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3806 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3807}
3808
Harry Cuttsb166c002023-05-09 13:06:05 +00003809TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3811 sp<FakeWindowHandle> window =
3812 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3813 window->setFrame(Rect(0, 0, 400, 400));
3814 sp<FakeWindowHandle> trustedOverlay =
3815 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3816 ADISPLAY_ID_DEFAULT);
3817 trustedOverlay->setSpy(true);
3818 trustedOverlay->setTrustedOverlay(true);
3819
3820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3821
3822 // Start a three-finger touchpad swipe
3823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3824 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3825 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3826 .build());
3827 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3828 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3829 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3830 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3831 .build());
3832 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3833 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3834 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3835 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3836 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3837 .build());
3838
3839 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3840 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3841 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3842
3843 // Move the swipe a bit
3844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3845 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3846 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3847 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3848 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3849 .build());
3850
3851 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3852
3853 // End the swipe
3854 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3855 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3856 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3857 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3858 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3859 .build());
3860 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3861 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3862 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3863 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3864 .build());
3865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3866 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3867 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3868 .build());
3869
3870 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3871 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3872 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3873
3874 window->assertNoEvents();
3875}
3876
3877TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3879 sp<FakeWindowHandle> window =
3880 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3881 window->setFrame(Rect(0, 0, 400, 400));
3882 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3883
3884 // Start a three-finger touchpad swipe
3885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3886 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3887 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3888 .build());
3889 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3890 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3891 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3892 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3893 .build());
3894 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3895 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3896 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3897 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3898 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3899 .build());
3900
3901 // Move the swipe a bit
3902 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3903 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3904 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3905 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3906 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3907 .build());
3908
3909 // End the swipe
3910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3911 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3912 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3913 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3914 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3915 .build());
3916 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3917 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3918 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3919 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3920 .build());
3921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3922 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3923 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3924 .build());
3925
3926 window->assertNoEvents();
3927}
3928
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003929/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003930 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3931 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003932 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003933 */
3934TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3936 sp<FakeWindowHandle> window =
3937 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3938 window->setFrame(Rect(0, 0, 400, 400));
3939 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3940
3941 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3942 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3943 .downTime(baseTime + 10)
3944 .eventTime(baseTime + 10)
3945 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3946 .build());
3947
3948 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3949
3950 // We need a new window object for the same window, because dispatcher will store objects by
3951 // reference. That means that the testing code and the dispatcher will refer to the same shared
3952 // object. Calling window->setTransform here would affect dispatcher's comparison
3953 // of the old window to the new window, since both the old window and the new window would be
3954 // updated to the same value.
3955 sp<FakeWindowHandle> windowDup = window->duplicate();
3956
3957 // Change the transform so that the orientation is now different from original.
3958 windowDup->setWindowTransform(0, -1, 1, 0);
3959
3960 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3961
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003962 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3963 .downTime(baseTime + 10)
3964 .eventTime(baseTime + 30)
3965 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3966 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3967 .build());
3968
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003969 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3970
3971 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003972 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3973 .downTime(baseTime + 10)
3974 .eventTime(baseTime + 40)
3975 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3976 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3977 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003978
3979 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3980
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3982 .downTime(baseTime + 10)
3983 .eventTime(baseTime + 50)
3984 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3985 .build());
3986
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003987 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
3988
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3990 .downTime(baseTime + 60)
3991 .eventTime(baseTime + 60)
3992 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
3993 .build());
3994
3995 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3996}
3997
3998/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003999 * Ensure the correct coordinate spaces are used by InputDispatcher.
4000 *
4001 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4002 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4003 * space.
4004 */
4005class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4006public:
4007 void SetUp() override {
4008 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004009 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004010 }
4011
4012 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4013 gui::DisplayInfo info;
4014 info.displayId = displayId;
4015 info.transform = transform;
4016 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004017 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004018 }
4019
4020 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4021 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004022 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004023 }
4024
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004025 void removeAllWindowsAndDisplays() {
4026 mDisplayInfos.clear();
4027 mWindowInfos.clear();
4028 }
4029
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004030 // Set up a test scenario where the display has a scaled projection and there are two windows
4031 // on the display.
4032 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4033 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4034 // respectively.
4035 ui::Transform displayTransform;
4036 displayTransform.set(2, 0, 0, 4);
4037 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4038
4039 std::shared_ptr<FakeApplicationHandle> application =
4040 std::make_shared<FakeApplicationHandle>();
4041
4042 // Add two windows to the display. Their frames are represented in the display space.
4043 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004044 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4045 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004046 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4047 addWindow(firstWindow);
4048
4049 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004050 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4051 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004052 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4053 addWindow(secondWindow);
4054 return {std::move(firstWindow), std::move(secondWindow)};
4055 }
4056
4057private:
4058 std::vector<gui::DisplayInfo> mDisplayInfos;
4059 std::vector<gui::WindowInfo> mWindowInfos;
4060};
4061
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004062TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004063 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4064 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004065 // selected so that if the hit test was performed with the point and the bounds being in
4066 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004067 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4068 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4069 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004070
4071 firstWindow->consumeMotionDown();
4072 secondWindow->assertNoEvents();
4073}
4074
4075// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4076// the event should be treated as being in the logical display space.
4077TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4078 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4079 // Send down to the first window. The point is represented in the logical display space. The
4080 // point is selected so that if the hit test was done in logical display space, then it would
4081 // end up in the incorrect window.
4082 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4083 PointF{75 * 2, 55 * 4});
4084
4085 firstWindow->consumeMotionDown();
4086 secondWindow->assertNoEvents();
4087}
4088
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004089// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4090// event should be treated as being in the logical display space.
4091TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4092 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4093
4094 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4095 ui::Transform injectedEventTransform;
4096 injectedEventTransform.set(matrix);
4097 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4098 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4099
4100 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4101 .displayId(ADISPLAY_ID_DEFAULT)
4102 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004103 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004104 .x(untransformedPoint.x)
4105 .y(untransformedPoint.y))
4106 .build();
4107 event.transform(matrix);
4108
4109 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4110 InputEventInjectionSync::WAIT_FOR_RESULT);
4111
4112 firstWindow->consumeMotionDown();
4113 secondWindow->assertNoEvents();
4114}
4115
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004116TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4117 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4118
4119 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004120 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4121 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4122 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004123
4124 firstWindow->assertNoEvents();
4125 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004126 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004127 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4128
4129 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4130 EXPECT_EQ(300, event->getRawX(0));
4131 EXPECT_EQ(880, event->getRawY(0));
4132
4133 // Ensure that the x and y values are in the window's coordinate space.
4134 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4135 // the logical display space. This will be the origin of the window space.
4136 EXPECT_EQ(100, event->getX(0));
4137 EXPECT_EQ(80, event->getY(0));
4138}
4139
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004140/** Ensure consistent behavior of InputDispatcher in all orientations. */
4141class InputDispatcherDisplayOrientationFixture
4142 : public InputDispatcherDisplayProjectionTest,
4143 public ::testing::WithParamInterface<ui::Rotation> {};
4144
4145// This test verifies the touchable region of a window for all rotations of the display by tapping
4146// in different locations on the display, specifically points close to the four corners of a
4147// window.
4148TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4149 constexpr static int32_t displayWidth = 400;
4150 constexpr static int32_t displayHeight = 800;
4151
4152 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4153
4154 const auto rotation = GetParam();
4155
4156 // Set up the display with the specified rotation.
4157 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4158 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4159 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4160 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4161 logicalDisplayWidth, logicalDisplayHeight);
4162 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4163
4164 // Create a window with its bounds determined in the logical display.
4165 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4166 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4167 sp<FakeWindowHandle> window =
4168 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4169 window->setFrame(frameInDisplay, displayTransform);
4170 addWindow(window);
4171
4172 // The following points in logical display space should be inside the window.
4173 static const std::array<vec2, 4> insidePoints{
4174 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4175 for (const auto pointInsideWindow : insidePoints) {
4176 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4177 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004178 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4179 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4180 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004181 window->consumeMotionDown();
4182
Prabir Pradhan678438e2023-04-13 19:32:51 +00004183 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4184 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4185 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004186 window->consumeMotionUp();
4187 }
4188
4189 // The following points in logical display space should be outside the window.
4190 static const std::array<vec2, 5> outsidePoints{
4191 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4192 for (const auto pointOutsideWindow : outsidePoints) {
4193 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4194 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004195 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4196 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4197 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004198
Prabir Pradhan678438e2023-04-13 19:32:51 +00004199 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4200 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4201 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004202 }
4203 window->assertNoEvents();
4204}
4205
4206// Run the precision tests for all rotations.
4207INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4208 InputDispatcherDisplayOrientationFixture,
4209 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4210 ui::ROTATION_270),
4211 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4212 return ftl::enum_string(testParamInfo.param);
4213 });
4214
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004215using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4216 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004217
4218class TransferTouchFixture : public InputDispatcherTest,
4219 public ::testing::WithParamInterface<TransferFunction> {};
4220
4221TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004223
4224 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004225 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004226 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4227 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004228 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004229 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004230 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4231 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004232 sp<FakeWindowHandle> wallpaper =
4233 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4234 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004235 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004236 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004237
4238 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004239 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4240 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004241
Svet Ganov5d3bc372020-01-26 23:11:07 -08004242 // Only the first window should get the down event
4243 firstWindow->consumeMotionDown();
4244 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004245 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004246
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004247 // Transfer touch to the second window
4248 TransferFunction f = GetParam();
4249 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4250 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004251 // The first window gets cancel and the second gets down
4252 firstWindow->consumeMotionCancel();
4253 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004254 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004255
4256 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004257 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4258 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004259 // The first window gets no events and the second gets up
4260 firstWindow->assertNoEvents();
4261 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004262 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004263}
4264
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004265/**
4266 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4267 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4268 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4269 * natural to the user.
4270 * In this test, we are sending a pointer to both spy window and first window. We then try to
4271 * transfer touch to the second window. The dispatcher should identify the first window as the
4272 * one that should lose the gesture, and therefore the action should be to move the gesture from
4273 * the first window to the second.
4274 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4275 * the other API, as well.
4276 */
4277TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4279
4280 // Create a couple of windows + a spy window
4281 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004282 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004283 spyWindow->setTrustedOverlay(true);
4284 spyWindow->setSpy(true);
4285 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004286 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004287 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004288 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004289
4290 // Add the windows to the dispatcher
4291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4292
4293 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4295 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004296 // Only the first window and spy should get the down event
4297 spyWindow->consumeMotionDown();
4298 firstWindow->consumeMotionDown();
4299
4300 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4301 // if f === 'transferTouch'.
4302 TransferFunction f = GetParam();
4303 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4304 ASSERT_TRUE(success);
4305 // The first window gets cancel and the second gets down
4306 firstWindow->consumeMotionCancel();
4307 secondWindow->consumeMotionDown();
4308
4309 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004310 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4311 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004312 // The first window gets no events and the second+spy get up
4313 firstWindow->assertNoEvents();
4314 spyWindow->consumeMotionUp();
4315 secondWindow->consumeMotionUp();
4316}
4317
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004318TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004320
4321 PointF touchPoint = {10, 10};
4322
4323 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004324 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004325 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4326 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004327 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004328 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004329 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4330 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004331 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004332
4333 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004334 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004335
4336 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004337 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4338 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4339 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004340 // Only the first window should get the down event
4341 firstWindow->consumeMotionDown();
4342 secondWindow->assertNoEvents();
4343
4344 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004345 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4346 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004347 // Only the first window should get the pointer down event
4348 firstWindow->consumeMotionPointerDown(1);
4349 secondWindow->assertNoEvents();
4350
4351 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004352 TransferFunction f = GetParam();
4353 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4354 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004355 // The first window gets cancel and the second gets down and pointer down
4356 firstWindow->consumeMotionCancel();
4357 secondWindow->consumeMotionDown();
4358 secondWindow->consumeMotionPointerDown(1);
4359
4360 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004361 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4362 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004363 // The first window gets nothing and the second gets pointer up
4364 firstWindow->assertNoEvents();
4365 secondWindow->consumeMotionPointerUp(1);
4366
4367 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004368 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4369 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004370 // The first window gets nothing and the second gets up
4371 firstWindow->assertNoEvents();
4372 secondWindow->consumeMotionUp();
4373}
4374
Arthur Hungc539dbb2022-12-08 07:45:36 +00004375TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4377
4378 // Create a couple of windows
4379 sp<FakeWindowHandle> firstWindow =
4380 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4381 ADISPLAY_ID_DEFAULT);
4382 firstWindow->setDupTouchToWallpaper(true);
4383 sp<FakeWindowHandle> secondWindow =
4384 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4385 ADISPLAY_ID_DEFAULT);
4386 secondWindow->setDupTouchToWallpaper(true);
4387
4388 sp<FakeWindowHandle> wallpaper1 =
4389 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4390 wallpaper1->setIsWallpaper(true);
4391
4392 sp<FakeWindowHandle> wallpaper2 =
4393 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4394 wallpaper2->setIsWallpaper(true);
4395 // Add the windows to the dispatcher
4396 mDispatcher->setInputWindows(
4397 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4398
4399 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004400 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4401 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004402
4403 // Only the first window should get the down event
4404 firstWindow->consumeMotionDown();
4405 secondWindow->assertNoEvents();
4406 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4407 wallpaper2->assertNoEvents();
4408
4409 // Transfer touch focus to the second window
4410 TransferFunction f = GetParam();
4411 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4412 ASSERT_TRUE(success);
4413
4414 // The first window gets cancel and the second gets down
4415 firstWindow->consumeMotionCancel();
4416 secondWindow->consumeMotionDown();
4417 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4418 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4419
4420 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004421 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4422 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004423 // The first window gets no events and the second gets up
4424 firstWindow->assertNoEvents();
4425 secondWindow->consumeMotionUp();
4426 wallpaper1->assertNoEvents();
4427 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4428}
4429
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004430// For the cases of single pointer touch and two pointers non-split touch, the api's
4431// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4432// for the case where there are multiple pointers split across several windows.
4433INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4434 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004435 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4436 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004437 return dispatcher->transferTouch(destChannelToken,
4438 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004439 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004440 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4441 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004442 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004443 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004444 }));
4445
Svet Ganov5d3bc372020-01-26 23:11:07 -08004446TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004448
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004449 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004450 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4451 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004452 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004453
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004454 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004455 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4456 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004457 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004458
4459 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004461
4462 PointF pointInFirst = {300, 200};
4463 PointF pointInSecond = {300, 600};
4464
4465 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004466 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4467 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4468 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004469 // Only the first window should get the down event
4470 firstWindow->consumeMotionDown();
4471 secondWindow->assertNoEvents();
4472
4473 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004474 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4475 ADISPLAY_ID_DEFAULT,
4476 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004477 // The first window gets a move and the second a down
4478 firstWindow->consumeMotionMove();
4479 secondWindow->consumeMotionDown();
4480
4481 // Transfer touch focus to the second window
4482 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4483 // The first window gets cancel and the new gets pointer down (it already saw down)
4484 firstWindow->consumeMotionCancel();
4485 secondWindow->consumeMotionPointerDown(1);
4486
4487 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004488 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4489 ADISPLAY_ID_DEFAULT,
4490 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004491 // The first window gets nothing and the second gets pointer up
4492 firstWindow->assertNoEvents();
4493 secondWindow->consumeMotionPointerUp(1);
4494
4495 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004496 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4497 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004498 // The first window gets nothing and the second gets up
4499 firstWindow->assertNoEvents();
4500 secondWindow->consumeMotionUp();
4501}
4502
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004503// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4504// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4505// touch is not supported, so the touch should continue on those windows and the transferred-to
4506// window should get nothing.
4507TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4509
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004510 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004511 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4512 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004513 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004514
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004515 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004516 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4517 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004518 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004519
4520 // Add the windows to the dispatcher
4521 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4522
4523 PointF pointInFirst = {300, 200};
4524 PointF pointInSecond = {300, 600};
4525
4526 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004527 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4528 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4529 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004530 // Only the first window should get the down event
4531 firstWindow->consumeMotionDown();
4532 secondWindow->assertNoEvents();
4533
4534 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004535 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4536 ADISPLAY_ID_DEFAULT,
4537 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004538 // The first window gets a move and the second a down
4539 firstWindow->consumeMotionMove();
4540 secondWindow->consumeMotionDown();
4541
4542 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004543 const bool transferred =
4544 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004545 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4546 ASSERT_FALSE(transferred);
4547 firstWindow->assertNoEvents();
4548 secondWindow->assertNoEvents();
4549
4550 // The rest of the dispatch should proceed as normal
4551 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004552 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4553 ADISPLAY_ID_DEFAULT,
4554 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004555 // The first window gets MOVE and the second gets pointer up
4556 firstWindow->consumeMotionMove();
4557 secondWindow->consumeMotionUp();
4558
4559 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004560 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4561 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004562 // The first window gets nothing and the second gets up
4563 firstWindow->consumeMotionUp();
4564 secondWindow->assertNoEvents();
4565}
4566
Arthur Hungabbb9d82021-09-01 14:52:30 +00004567// This case will create two windows and one mirrored window on the default display and mirror
4568// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4569// the windows info of second display before default display.
4570TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4572 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004573 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004574 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004575 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004576 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004577 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004578
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004579 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004580 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004581
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004582 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004584
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004585 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004586 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004587
4588 // Update window info, let it find window handle of second display first.
4589 mDispatcher->setInputWindows(
4590 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4591 {ADISPLAY_ID_DEFAULT,
4592 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4593
4594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4595 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4596 {50, 50}))
4597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4598
4599 // Window should receive motion event.
4600 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4601
4602 // Transfer touch focus
4603 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4604 secondWindowInPrimary->getToken()));
4605 // The first window gets cancel.
4606 firstWindowInPrimary->consumeMotionCancel();
4607 secondWindowInPrimary->consumeMotionDown();
4608
4609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4610 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4611 ADISPLAY_ID_DEFAULT, {150, 50}))
4612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4613 firstWindowInPrimary->assertNoEvents();
4614 secondWindowInPrimary->consumeMotionMove();
4615
4616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4617 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4618 {150, 50}))
4619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4620 firstWindowInPrimary->assertNoEvents();
4621 secondWindowInPrimary->consumeMotionUp();
4622}
4623
4624// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4625// 'transferTouch' api.
4626TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4628 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004629 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004630 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004631 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004632 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004633 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004634
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004635 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004636 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004637
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004638 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004639 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004640
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004641 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004643
4644 // Update window info, let it find window handle of second display first.
4645 mDispatcher->setInputWindows(
4646 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4647 {ADISPLAY_ID_DEFAULT,
4648 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4649
4650 // Touch on second display.
4651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4652 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4654
4655 // Window should receive motion event.
4656 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4657
4658 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004659 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004660
4661 // The first window gets cancel.
4662 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4663 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4664
4665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4666 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4667 SECOND_DISPLAY_ID, {150, 50}))
4668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4669 firstWindowInPrimary->assertNoEvents();
4670 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4671
4672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4673 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4675 firstWindowInPrimary->assertNoEvents();
4676 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4677}
4678
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004679TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4682 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004683
Vishnu Nair47074b82020-08-14 11:54:47 -07004684 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004685 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004686 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004687
4688 window->consumeFocusEvent(true);
4689
Prabir Pradhan678438e2023-04-13 19:32:51 +00004690 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004691
4692 // Window should receive key down event.
4693 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004694
4695 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004696 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004697 mFakePolicy->assertUserActivityPoked();
4698}
4699
4700TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4702 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4703 "Fake Window", ADISPLAY_ID_DEFAULT);
4704
4705 window->setDisableUserActivity(true);
4706 window->setFocusable(true);
4707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4708 setFocusedWindow(window);
4709
4710 window->consumeFocusEvent(true);
4711
4712 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4713
4714 // Window should receive key down event.
4715 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4716
4717 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004718 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004719 mFakePolicy->assertUserActivityNotPoked();
4720}
4721
4722TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4724 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4725 "Fake Window", ADISPLAY_ID_DEFAULT);
4726
4727 window->setFocusable(true);
4728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4729 setFocusedWindow(window);
4730
4731 window->consumeFocusEvent(true);
4732
4733 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4734 mDispatcher->waitForIdle();
4735
4736 // System key is not passed down
4737 window->assertNoEvents();
4738
4739 // Should have poked user activity
4740 mFakePolicy->assertUserActivityPoked();
4741}
4742
4743TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4745 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4746 "Fake Window", ADISPLAY_ID_DEFAULT);
4747
4748 window->setFocusable(true);
4749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4750 setFocusedWindow(window);
4751
4752 window->consumeFocusEvent(true);
4753
4754 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4755 mDispatcher->waitForIdle();
4756
4757 // System key is not passed down
4758 window->assertNoEvents();
4759
4760 // Should have poked user activity
4761 mFakePolicy->assertUserActivityPoked();
4762}
4763
4764TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4766 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4767 "Fake Window", ADISPLAY_ID_DEFAULT);
4768
4769 window->setDisableUserActivity(true);
4770 window->setFocusable(true);
4771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4772 setFocusedWindow(window);
4773
4774 window->consumeFocusEvent(true);
4775
4776 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4777 mDispatcher->waitForIdle();
4778
4779 // System key is not passed down
4780 window->assertNoEvents();
4781
4782 // Should have poked user activity
4783 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004784}
4785
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004786TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4789 "Fake Window", ADISPLAY_ID_DEFAULT);
4790
4791 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4792
4793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4794 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4795 ADISPLAY_ID_DEFAULT, {100, 100}))
4796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4797
4798 window->consumeMotionEvent(
4799 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4800
4801 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004802 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004803 mFakePolicy->assertUserActivityPoked();
4804}
4805
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004806TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004807 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004808 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4809 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004810
Arthur Hung72d8dc32020-03-28 00:48:39 +00004811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004812
Prabir Pradhan678438e2023-04-13 19:32:51 +00004813 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004814 mDispatcher->waitForIdle();
4815
4816 window->assertNoEvents();
4817}
4818
4819// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4820TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004822 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4823 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004824
Arthur Hung72d8dc32020-03-28 00:48:39 +00004825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004826
4827 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004828 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004829 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004830 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4831 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004832
4833 // Window should receive only the motion event
4834 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4835 window->assertNoEvents(); // Key event or focus event will not be received
4836}
4837
arthurhungea3f4fc2020-12-21 23:18:53 +08004838TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4840
arthurhungea3f4fc2020-12-21 23:18:53 +08004841 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004842 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4843 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004844 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004845
arthurhungea3f4fc2020-12-21 23:18:53 +08004846 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004847 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4848 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004849 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004850
4851 // Add the windows to the dispatcher
4852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4853
4854 PointF pointInFirst = {300, 200};
4855 PointF pointInSecond = {300, 600};
4856
4857 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004858 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4859 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4860 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004861 // Only the first window should get the down event
4862 firstWindow->consumeMotionDown();
4863 secondWindow->assertNoEvents();
4864
4865 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004866 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4867 ADISPLAY_ID_DEFAULT,
4868 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004869 // The first window gets a move and the second a down
4870 firstWindow->consumeMotionMove();
4871 secondWindow->consumeMotionDown();
4872
4873 // Send pointer cancel to the second window
4874 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004875 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004876 {pointInFirst, pointInSecond});
4877 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004878 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004879 // The first window gets move and the second gets cancel.
4880 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4881 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4882
4883 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004884 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4885 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004886 // The first window gets up and the second gets nothing.
4887 firstWindow->consumeMotionUp();
4888 secondWindow->assertNoEvents();
4889}
4890
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004891TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4893
4894 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004895 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004896 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4897 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4898 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4899 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4900
Harry Cutts33476232023-01-30 19:57:29 +00004901 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004902 window->assertNoEvents();
4903 mDispatcher->waitForIdle();
4904}
4905
chaviwd1c23182019-12-20 18:44:56 -08004906class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004907public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004908 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004909 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004910 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004911 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004912 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004913 }
4914
chaviwd1c23182019-12-20 18:44:56 -08004915 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4916
4917 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004918 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4919 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004920 }
4921
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004922 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4923
4924 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4925
chaviwd1c23182019-12-20 18:44:56 -08004926 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004927 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004928 expectedDisplayId, expectedFlags);
4929 }
4930
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004931 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004932 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004933 expectedDisplayId, expectedFlags);
4934 }
4935
chaviwd1c23182019-12-20 18:44:56 -08004936 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004937 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004938 expectedDisplayId, expectedFlags);
4939 }
4940
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004941 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004942 mInputReceiver->consumeMotionEvent(
4943 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4944 WithDisplayId(expectedDisplayId),
4945 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004946 }
4947
Arthur Hungfbfa5722021-11-16 02:45:54 +00004948 void consumeMotionPointerDown(int32_t pointerIdx) {
4949 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4950 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004951 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004952 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004953 }
4954
Evan Rosky84f07f02021-04-16 10:42:42 -07004955 MotionEvent* consumeMotion() {
4956 InputEvent* event = mInputReceiver->consume();
4957 if (!event) {
4958 ADD_FAILURE() << "No event was produced";
4959 return nullptr;
4960 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004961 if (event->getType() != InputEventType::MOTION) {
4962 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004963 return nullptr;
4964 }
4965 return static_cast<MotionEvent*>(event);
4966 }
4967
chaviwd1c23182019-12-20 18:44:56 -08004968 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4969
4970private:
4971 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004972};
4973
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004974using InputDispatcherMonitorTest = InputDispatcherTest;
4975
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004976/**
4977 * Two entities that receive touch: A window, and a global monitor.
4978 * The touch goes to the window, and then the window disappears.
4979 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4980 * for the monitor, as well.
4981 * 1. foregroundWindow
4982 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4983 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004984TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004985 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4986 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004987 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004988
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004989 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004990
4991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4993 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4994 {100, 200}))
4995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4996
4997 // Both the foreground window and the global monitor should receive the touch down
4998 window->consumeMotionDown();
4999 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5000
5001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5002 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5003 ADISPLAY_ID_DEFAULT, {110, 200}))
5004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5005
5006 window->consumeMotionMove();
5007 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5008
5009 // Now the foreground window goes away
5010 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5011 window->consumeMotionCancel();
5012 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5013
5014 // If more events come in, there will be no more foreground window to send them to. This will
5015 // cause a cancel for the monitor, as well.
5016 ASSERT_EQ(InputEventInjectionResult::FAILED,
5017 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5018 ADISPLAY_ID_DEFAULT, {120, 200}))
5019 << "Injection should fail because the window was removed";
5020 window->assertNoEvents();
5021 // Global monitor now gets the cancel
5022 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5023}
5024
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005025TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005027 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5028 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005030
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005031 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005034 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005036 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005037 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005038}
5039
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005040TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5041 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005042
Chris Yea209fde2020-07-22 13:54:51 -07005043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005044 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5045 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005047
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005051 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005052 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005053
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005054 // Pilfer pointers from the monitor.
5055 // This should not do anything and the window should continue to receive events.
5056 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005057
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005059 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5060 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005062
5063 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5064 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005065}
5066
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005067TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005069 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5070 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005071 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5072 window->setWindowOffset(20, 40);
5073 window->setWindowTransform(0, 1, -1, 0);
5074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005075 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005076
5077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5078 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5079 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5080 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5081 MotionEvent* event = monitor.consumeMotion();
5082 // Even though window has transform, gesture monitor must not.
5083 ASSERT_EQ(ui::Transform(), event->getTransform());
5084}
5085
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005086TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005088 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005089
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005090 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005091 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005092 << "Injection should fail if there is a monitor, but no touchable window";
5093 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005094}
5095
chaviw81e2bb92019-12-18 15:03:51 -08005096TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005098 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5099 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005100
Arthur Hung72d8dc32020-03-28 00:48:39 +00005101 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005102
5103 NotifyMotionArgs motionArgs =
5104 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5105 ADISPLAY_ID_DEFAULT);
5106
Prabir Pradhan678438e2023-04-13 19:32:51 +00005107 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005108 // Window should receive motion down event.
5109 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5110
5111 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005112 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005113 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5114 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5115 motionArgs.pointerCoords[0].getX() - 10);
5116
Prabir Pradhan678438e2023-04-13 19:32:51 +00005117 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005118 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005119 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005120}
5121
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005122/**
5123 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5124 * the device default right away. In the test scenario, we check both the default value,
5125 * and the action of enabling / disabling.
5126 */
5127TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005128 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005129 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5130 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005131 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005132
5133 // Set focused application.
5134 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005135 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005136
5137 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005138 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005139 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005140 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005141
5142 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005143 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005144 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005145 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005146
5147 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005148 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005149 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005150 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005151 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005153 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005154 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005155
5156 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005157 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005159 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005160
5161 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005162 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005163 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005164 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005165 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005166 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005167 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005168 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005169
5170 window->assertNoEvents();
5171}
5172
Gang Wange9087892020-01-07 12:17:14 -05005173TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005175 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5176 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005177
5178 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005179 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005180
Arthur Hung72d8dc32020-03-28 00:48:39 +00005181 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005182 setFocusedWindow(window);
5183
Harry Cutts33476232023-01-30 19:57:29 +00005184 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005185
Prabir Pradhan678438e2023-04-13 19:32:51 +00005186 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5187 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005188
5189 InputEvent* event = window->consume();
5190 ASSERT_NE(event, nullptr);
5191
5192 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5193 ASSERT_NE(verified, nullptr);
5194 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5195
5196 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5197 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5198 ASSERT_EQ(keyArgs.source, verified->source);
5199 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5200
5201 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5202
5203 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005204 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005205 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005206 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5207 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5208 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5209 ASSERT_EQ(0, verifiedKey.repeatCount);
5210}
5211
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005212TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005214 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5215 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005216
5217 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5218
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005219 ui::Transform transform;
5220 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5221
5222 gui::DisplayInfo displayInfo;
5223 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5224 displayInfo.transform = transform;
5225
Patrick Williamsd828f302023-04-28 17:52:08 -05005226 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005227
Prabir Pradhan678438e2023-04-13 19:32:51 +00005228 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005229 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5230 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005231 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005232
5233 InputEvent* event = window->consume();
5234 ASSERT_NE(event, nullptr);
5235
5236 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5237 ASSERT_NE(verified, nullptr);
5238 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5239
5240 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5241 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5242 EXPECT_EQ(motionArgs.source, verified->source);
5243 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5244
5245 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5246
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005247 const vec2 rawXY =
5248 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5249 motionArgs.pointerCoords[0].getXYValue());
5250 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5251 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005252 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005253 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005254 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005255 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5256 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5257}
5258
chaviw09c8d2d2020-08-24 15:48:26 -07005259/**
5260 * Ensure that separate calls to sign the same data are generating the same key.
5261 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5262 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5263 * tests.
5264 */
5265TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5266 KeyEvent event = getTestKeyEvent();
5267 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5268
5269 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5270 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5271 ASSERT_EQ(hmac1, hmac2);
5272}
5273
5274/**
5275 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5276 */
5277TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5278 KeyEvent event = getTestKeyEvent();
5279 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5280 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5281
5282 verifiedEvent.deviceId += 1;
5283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5284
5285 verifiedEvent.source += 1;
5286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5287
5288 verifiedEvent.eventTimeNanos += 1;
5289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5290
5291 verifiedEvent.displayId += 1;
5292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5293
5294 verifiedEvent.action += 1;
5295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5296
5297 verifiedEvent.downTimeNanos += 1;
5298 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5299
5300 verifiedEvent.flags += 1;
5301 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5302
5303 verifiedEvent.keyCode += 1;
5304 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5305
5306 verifiedEvent.scanCode += 1;
5307 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5308
5309 verifiedEvent.metaState += 1;
5310 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5311
5312 verifiedEvent.repeatCount += 1;
5313 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5314}
5315
Vishnu Nair958da932020-08-21 17:12:37 -07005316TEST_F(InputDispatcherTest, SetFocusedWindow) {
5317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5318 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005319 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005320 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005321 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005322 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5323
5324 // Top window is also focusable but is not granted focus.
5325 windowTop->setFocusable(true);
5326 windowSecond->setFocusable(true);
5327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5328 setFocusedWindow(windowSecond);
5329
5330 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5332 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005333
5334 // Focused window should receive event.
5335 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5336 windowTop->assertNoEvents();
5337}
5338
5339TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5341 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005342 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005343 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5344
5345 window->setFocusable(true);
5346 // Release channel for window is no longer valid.
5347 window->releaseChannel();
5348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5349 setFocusedWindow(window);
5350
5351 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005352 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5353 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005354
5355 // window channel is invalid, so it should not receive any input event.
5356 window->assertNoEvents();
5357}
5358
5359TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5361 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005362 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005363 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5365
Vishnu Nair958da932020-08-21 17:12:37 -07005366 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5367 setFocusedWindow(window);
5368
5369 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005370 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5371 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005372
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005373 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005374 window->assertNoEvents();
5375}
5376
5377TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5379 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005380 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005381 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005382 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005383 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5384
5385 windowTop->setFocusable(true);
5386 windowSecond->setFocusable(true);
5387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5388 setFocusedWindow(windowTop);
5389 windowTop->consumeFocusEvent(true);
5390
Chavi Weingarten847e8512023-03-29 00:26:09 +00005391 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5392 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005393 windowSecond->consumeFocusEvent(true);
5394 windowTop->consumeFocusEvent(false);
5395
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5397 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005398
5399 // Focused window should receive event.
5400 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5401}
5402
Chavi Weingarten847e8512023-03-29 00:26:09 +00005403TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5405 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005406 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005407 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005408 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005409 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5410
5411 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005412 windowSecond->setFocusable(false);
5413 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005414 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005415 setFocusedWindow(windowTop);
5416 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005417
Chavi Weingarten847e8512023-03-29 00:26:09 +00005418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5419 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005420
5421 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005422 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005423 windowSecond->assertNoEvents();
5424}
5425
5426TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5428 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005429 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005430 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005431 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5432 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005433 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5434
5435 window->setFocusable(true);
5436 previousFocusedWindow->setFocusable(true);
5437 window->setVisible(false);
5438 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5439 setFocusedWindow(previousFocusedWindow);
5440 previousFocusedWindow->consumeFocusEvent(true);
5441
5442 // Requesting focus on invisible window takes focus from currently focused window.
5443 setFocusedWindow(window);
5444 previousFocusedWindow->consumeFocusEvent(false);
5445
5446 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005448 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5449 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005450
5451 // Window does not get focus event or key down.
5452 window->assertNoEvents();
5453
5454 // Window becomes visible.
5455 window->setVisible(true);
5456 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5457
5458 // Window receives focus event.
5459 window->consumeFocusEvent(true);
5460 // Focused window receives key down.
5461 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5462}
5463
Vishnu Nair599f1412021-06-21 10:39:58 -07005464TEST_F(InputDispatcherTest, DisplayRemoved) {
5465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5466 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005467 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005468 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5469
5470 // window is granted focus.
5471 window->setFocusable(true);
5472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5473 setFocusedWindow(window);
5474 window->consumeFocusEvent(true);
5475
5476 // When a display is removed window loses focus.
5477 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5478 window->consumeFocusEvent(false);
5479}
5480
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005481/**
5482 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5483 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5484 * of the 'slipperyEnterWindow'.
5485 *
5486 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5487 * a way so that the touched location is no longer covered by the top window.
5488 *
5489 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5490 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5491 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5492 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5493 * with ACTION_DOWN).
5494 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5495 * window moved itself away from the touched location and had Flag::SLIPPERY.
5496 *
5497 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5498 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5499 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5500 *
5501 * In this test, we ensure that the event received by the bottom window has
5502 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5503 */
5504TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005505 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005506 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005507
5508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5509 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5510
5511 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005512 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005513 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005514 // Make sure this one overlaps the bottom window
5515 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5516 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5517 // one. Windows with the same owner are not considered to be occluding each other.
5518 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5519
5520 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005521 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005522 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5523
5524 mDispatcher->setInputWindows(
5525 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5526
5527 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5529 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5530 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005531 slipperyExitWindow->consumeMotionDown();
5532 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5533 mDispatcher->setInputWindows(
5534 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5535
Prabir Pradhan678438e2023-04-13 19:32:51 +00005536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5537 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5538 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005539
5540 slipperyExitWindow->consumeMotionCancel();
5541
5542 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5543 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5544}
5545
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005546/**
5547 * Two windows, one on the left and another on the right. The left window is slippery. The right
5548 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5549 * touch moves from the left window into the right window, the gesture should continue to go to the
5550 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5551 * reproduces a crash.
5552 */
5553TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5555
5556 sp<FakeWindowHandle> leftSlipperyWindow =
5557 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5558 leftSlipperyWindow->setSlippery(true);
5559 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5560
5561 sp<FakeWindowHandle> rightDropTouchesWindow =
5562 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5563 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5564 rightDropTouchesWindow->setDropInput(true);
5565
5566 mDispatcher->setInputWindows(
5567 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5568
5569 // Start touch in the left window
5570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5571 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5572 .build());
5573 leftSlipperyWindow->consumeMotionDown();
5574
5575 // And move it into the right window
5576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5577 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5578 .build());
5579
5580 // Since the right window isn't eligible to receive input, touch does not slip.
5581 // The left window continues to receive the gesture.
5582 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5583 rightDropTouchesWindow->assertNoEvents();
5584}
5585
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005586TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005587 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5589
5590 sp<FakeWindowHandle> leftWindow =
5591 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5592 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005593 leftWindow->setOwnerInfo(1, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005594
5595 sp<FakeWindowHandle> rightSpy =
5596 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5597 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005598 rightSpy->setOwnerInfo(2, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005599 rightSpy->setSpy(true);
5600 rightSpy->setTrustedOverlay(true);
5601
5602 sp<FakeWindowHandle> rightWindow =
5603 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5604 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005605 rightWindow->setOwnerInfo(3, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005606
5607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5608
5609 // Touch in the left window
5610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5611 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5612 .build());
5613 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5614 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005615 ASSERT_NO_FATAL_FAILURE(
5616 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005617
5618 // Touch another finger over the right windows
5619 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5620 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5621 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5622 .build());
5623 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5624 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5625 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5626 mDispatcher->waitForIdle();
5627 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005628 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5629 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005630
5631 // Release finger over left window. The UP actions are not treated as device interaction.
5632 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5633 // is part of the UP action, we do not treat this as device interaction.
5634 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5635 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5636 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5637 .build());
5638 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5639 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5640 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5641 mDispatcher->waitForIdle();
5642 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5643
5644 // Move remaining finger
5645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5646 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5647 .build());
5648 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5649 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5650 mDispatcher->waitForIdle();
5651 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005652 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005653
5654 // Release all fingers
5655 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5656 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5657 .build());
5658 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5659 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5660 mDispatcher->waitForIdle();
5661 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5662}
5663
5664TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5666
5667 sp<FakeWindowHandle> window =
5668 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5669 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005670 window->setOwnerInfo(1, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005671
5672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5673 setFocusedWindow(window);
5674 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5675
5676 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5677 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5678 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005679 ASSERT_NO_FATAL_FAILURE(
5680 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005681
5682 // The UP actions are not treated as device interaction.
5683 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5684 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5685 mDispatcher->waitForIdle();
5686 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5687}
5688
Garfield Tan1c7bc862020-01-28 13:24:04 -08005689class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5690protected:
5691 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5692 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5693
Chris Yea209fde2020-07-22 13:54:51 -07005694 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005695 sp<FakeWindowHandle> mWindow;
5696
5697 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005698 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005699 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005700 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005701 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005702 ASSERT_EQ(OK, mDispatcher->start());
5703
5704 setUpWindow();
5705 }
5706
5707 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005708 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005709 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005710
Vishnu Nair47074b82020-08-14 11:54:47 -07005711 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005712 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005713 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005714 mWindow->consumeFocusEvent(true);
5715 }
5716
Chris Ye2ad95392020-09-01 13:44:44 -07005717 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005718 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005719 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005720 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005721 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005722
5723 // Window should receive key down event.
5724 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5725 }
5726
5727 void expectKeyRepeatOnce(int32_t repeatCount) {
5728 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5729 InputEvent* repeatEvent = mWindow->consume();
5730 ASSERT_NE(nullptr, repeatEvent);
5731
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005732 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005733
5734 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5735 uint32_t eventAction = repeatKeyEvent->getAction();
5736 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5737 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5738 }
5739
Chris Ye2ad95392020-09-01 13:44:44 -07005740 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005741 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005742 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005743 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005744 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005745
5746 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005747 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005748 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005749 }
5750};
5751
5752TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005753 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005754 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5755 expectKeyRepeatOnce(repeatCount);
5756 }
5757}
5758
5759TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005760 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005761 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5762 expectKeyRepeatOnce(repeatCount);
5763 }
Harry Cutts33476232023-01-30 19:57:29 +00005764 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005765 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005766 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5767 expectKeyRepeatOnce(repeatCount);
5768 }
5769}
5770
5771TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005772 sendAndConsumeKeyDown(/*deviceId=*/1);
5773 expectKeyRepeatOnce(/*repeatCount=*/1);
5774 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005775 mWindow->assertNoEvents();
5776}
5777
5778TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005779 sendAndConsumeKeyDown(/*deviceId=*/1);
5780 expectKeyRepeatOnce(/*repeatCount=*/1);
5781 sendAndConsumeKeyDown(/*deviceId=*/2);
5782 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005783 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005784 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005785 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005786 expectKeyRepeatOnce(/*repeatCount=*/2);
5787 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005788 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005789 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005790 mWindow->assertNoEvents();
5791}
5792
5793TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005794 sendAndConsumeKeyDown(/*deviceId=*/1);
5795 expectKeyRepeatOnce(/*repeatCount=*/1);
5796 sendAndConsumeKeyDown(/*deviceId=*/2);
5797 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005798 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005799 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005800 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005801 mWindow->assertNoEvents();
5802}
5803
liushenxiang42232912021-05-21 20:24:09 +08005804TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5805 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005806 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005807 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005808 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5809 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5810 mWindow->assertNoEvents();
5811}
5812
Garfield Tan1c7bc862020-01-28 13:24:04 -08005813TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005814 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005815 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005816 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5817 InputEvent* repeatEvent = mWindow->consume();
5818 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5819 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5820 IdGenerator::getSource(repeatEvent->getId()));
5821 }
5822}
5823
5824TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005825 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005826 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005827
5828 std::unordered_set<int32_t> idSet;
5829 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5830 InputEvent* repeatEvent = mWindow->consume();
5831 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5832 int32_t id = repeatEvent->getId();
5833 EXPECT_EQ(idSet.end(), idSet.find(id));
5834 idSet.insert(id);
5835 }
5836}
5837
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005838/* Test InputDispatcher for MultiDisplay */
5839class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5840public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005841 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005842 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005843
Chris Yea209fde2020-07-22 13:54:51 -07005844 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005845 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005846 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005847
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005848 // Set focus window for primary display, but focused display would be second one.
5849 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005850 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005851 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005852 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005853 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005854
Chris Yea209fde2020-07-22 13:54:51 -07005855 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005856 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005857 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005858 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005859 // Set focus display to second one.
5860 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5861 // Set focus window for second display.
5862 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005863 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005864 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005865 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005866 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005867 }
5868
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005869 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005870 InputDispatcherTest::TearDown();
5871
Chris Yea209fde2020-07-22 13:54:51 -07005872 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005873 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005874 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 windowInSecondary.clear();
5876 }
5877
5878protected:
Chris Yea209fde2020-07-22 13:54:51 -07005879 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005880 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005881 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005882 sp<FakeWindowHandle> windowInSecondary;
5883};
5884
5885TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5886 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5888 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005890 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005891 windowInSecondary->assertNoEvents();
5892
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005893 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5895 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005897 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005898 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005899}
5900
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005901TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005902 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5904 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005905 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005906 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005907 windowInSecondary->assertNoEvents();
5908
5909 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005911 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005912 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005913 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005914
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005915 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005916 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005917
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005918 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005919 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005920 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005921
5922 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005923 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005924 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005925 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005926 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005927 windowInSecondary->assertNoEvents();
5928}
5929
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005930// Test per-display input monitors for motion event.
5931TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005932 FakeMonitorReceiver monitorInPrimary =
5933 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5934 FakeMonitorReceiver monitorInSecondary =
5935 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005936
5937 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5939 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005941 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005942 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005943 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005944 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005945
5946 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5948 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005950 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005951 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005952 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005953 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005954
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005955 // Lift up the touch from the second display
5956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5957 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5958 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5959 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5960 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5961
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005962 // Test inject a non-pointer motion event.
5963 // If specific a display, it will dispatch to the focused window of particular display,
5964 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5966 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005968 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005969 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005970 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005971 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005972}
5973
5974// Test per-display input monitors for key event.
5975TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005976 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005977 FakeMonitorReceiver monitorInPrimary =
5978 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5979 FakeMonitorReceiver monitorInSecondary =
5980 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005981
5982 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5984 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005985 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005986 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005987 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005988 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005989}
5990
Vishnu Nair958da932020-08-21 17:12:37 -07005991TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5992 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005993 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005994 secondWindowInPrimary->setFocusable(true);
5995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5996 setFocusedWindow(secondWindowInPrimary);
5997 windowInPrimary->consumeFocusEvent(false);
5998 secondWindowInPrimary->consumeFocusEvent(true);
5999
6000 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6002 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006003 windowInPrimary->assertNoEvents();
6004 windowInSecondary->assertNoEvents();
6005 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6006}
6007
Arthur Hungdfd528e2021-12-08 13:23:04 +00006008TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6009 FakeMonitorReceiver monitorInPrimary =
6010 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6011 FakeMonitorReceiver monitorInSecondary =
6012 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6013
6014 // Test touch down on primary display.
6015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6016 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6018 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6019 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6020
6021 // Test touch down on second display.
6022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6023 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6025 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6026 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6027
6028 // Trigger cancel touch.
6029 mDispatcher->cancelCurrentTouch();
6030 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6031 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6032 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6033 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6034
6035 // Test inject a move motion event, no window/monitor should receive the event.
6036 ASSERT_EQ(InputEventInjectionResult::FAILED,
6037 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6038 ADISPLAY_ID_DEFAULT, {110, 200}))
6039 << "Inject motion event should return InputEventInjectionResult::FAILED";
6040 windowInPrimary->assertNoEvents();
6041 monitorInPrimary.assertNoEvents();
6042
6043 ASSERT_EQ(InputEventInjectionResult::FAILED,
6044 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6045 SECOND_DISPLAY_ID, {110, 200}))
6046 << "Inject motion event should return InputEventInjectionResult::FAILED";
6047 windowInSecondary->assertNoEvents();
6048 monitorInSecondary.assertNoEvents();
6049}
6050
Jackal Guof9696682018-10-05 12:23:23 +08006051class InputFilterTest : public InputDispatcherTest {
6052protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006053 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6054 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006055 NotifyMotionArgs motionArgs;
6056
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006057 motionArgs =
6058 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006059 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006060 motionArgs =
6061 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006062 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006063 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006064 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006065 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
6066 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006067 } else {
6068 mFakePolicy->assertFilterInputEventWasNotCalled();
6069 }
6070 }
6071
6072 void testNotifyKey(bool expectToBeFiltered) {
6073 NotifyKeyArgs keyArgs;
6074
6075 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006076 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006077 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006078 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006079 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006080
6081 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006082 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006083 } else {
6084 mFakePolicy->assertFilterInputEventWasNotCalled();
6085 }
6086 }
6087};
6088
6089// Test InputFilter for MotionEvent
6090TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6091 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6092 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6093 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6094
6095 // Enable InputFilter
6096 mDispatcher->setInputFilterEnabled(true);
6097 // Test touch on both primary and second display, and check if both events are filtered.
6098 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6099 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6100
6101 // Disable InputFilter
6102 mDispatcher->setInputFilterEnabled(false);
6103 // Test touch on both primary and second display, and check if both events aren't filtered.
6104 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6105 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6106}
6107
6108// Test InputFilter for KeyEvent
6109TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6110 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6111 testNotifyKey(/*expectToBeFiltered*/ false);
6112
6113 // Enable InputFilter
6114 mDispatcher->setInputFilterEnabled(true);
6115 // Send a key event, and check if it is filtered.
6116 testNotifyKey(/*expectToBeFiltered*/ true);
6117
6118 // Disable InputFilter
6119 mDispatcher->setInputFilterEnabled(false);
6120 // Send a key event, and check if it isn't filtered.
6121 testNotifyKey(/*expectToBeFiltered*/ false);
6122}
6123
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006124// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6125// logical display coordinate space.
6126TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6127 ui::Transform firstDisplayTransform;
6128 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6129 ui::Transform secondDisplayTransform;
6130 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6131
6132 std::vector<gui::DisplayInfo> displayInfos(2);
6133 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6134 displayInfos[0].transform = firstDisplayTransform;
6135 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6136 displayInfos[1].transform = secondDisplayTransform;
6137
Patrick Williamsd828f302023-04-28 17:52:08 -05006138 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006139
6140 // Enable InputFilter
6141 mDispatcher->setInputFilterEnabled(true);
6142
6143 // Ensure the correct transforms are used for the displays.
6144 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6145 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6146}
6147
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006148class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6149protected:
6150 virtual void SetUp() override {
6151 InputDispatcherTest::SetUp();
6152
6153 /**
6154 * We don't need to enable input filter to test the injected event policy, but we enabled it
6155 * here to make the tests more realistic, since this policy only matters when inputfilter is
6156 * on.
6157 */
6158 mDispatcher->setInputFilterEnabled(true);
6159
6160 std::shared_ptr<InputApplicationHandle> application =
6161 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006162 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6163 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006164
6165 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6166 mWindow->setFocusable(true);
6167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6168 setFocusedWindow(mWindow);
6169 mWindow->consumeFocusEvent(true);
6170 }
6171
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006172 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6173 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006174 KeyEvent event;
6175
6176 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6177 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6178 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006179 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006180 const int32_t additionalPolicyFlags =
6181 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006183 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006184 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6185 policyFlags | additionalPolicyFlags));
6186
6187 InputEvent* received = mWindow->consume();
6188 ASSERT_NE(nullptr, received);
6189 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006190 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006191 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6192 ASSERT_EQ(flags, keyEvent.getFlags());
6193 }
6194
6195 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6196 int32_t flags) {
6197 MotionEvent event;
6198 PointerProperties pointerProperties[1];
6199 PointerCoords pointerCoords[1];
6200 pointerProperties[0].clear();
6201 pointerProperties[0].id = 0;
6202 pointerCoords[0].clear();
6203 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6204 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6205
6206 ui::Transform identityTransform;
6207 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6208 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6209 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6210 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6211 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006212 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006213 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006214 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6215
6216 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006218 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006219 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6220 policyFlags | additionalPolicyFlags));
6221
6222 InputEvent* received = mWindow->consume();
6223 ASSERT_NE(nullptr, received);
6224 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006225 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006226 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6227 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006228 }
6229
6230private:
6231 sp<FakeWindowHandle> mWindow;
6232};
6233
6234TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006235 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6236 // filter. Without it, the event will no different from a regularly injected event, and the
6237 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006238 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6239 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006240}
6241
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006242TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006243 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006244 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006245 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6246}
6247
6248TEST_F(InputFilterInjectionPolicyTest,
6249 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6250 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006251 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006252 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006253}
6254
6255TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006256 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6257 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006258}
6259
chaviwfd6d3512019-03-25 13:23:49 -07006260class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006261 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006262 InputDispatcherTest::SetUp();
6263
Chris Yea209fde2020-07-22 13:54:51 -07006264 std::shared_ptr<FakeApplicationHandle> application =
6265 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006266 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006267 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006268 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006269
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006270 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006271 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006272 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006273
6274 // Set focused application.
6275 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006276 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006277
6278 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006279 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006280 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006281 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006282 }
6283
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006284 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006285 InputDispatcherTest::TearDown();
6286
6287 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006288 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006289 }
6290
6291protected:
6292 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006293 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006294 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006295};
6296
6297// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6298// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6299// the onPointerDownOutsideFocus callback.
6300TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006302 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6303 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006305 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006306
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006307 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006308 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6309}
6310
6311// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6312// DOWN on the window that doesn't have focus. Ensure no window received the
6313// onPointerDownOutsideFocus callback.
6314TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006316 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006318 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006319
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006320 ASSERT_TRUE(mDispatcher->waitForIdle());
6321 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006322}
6323
6324// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6325// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6326TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6328 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006329 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006330 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006331
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006332 ASSERT_TRUE(mDispatcher->waitForIdle());
6333 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006334}
6335
6336// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6337// DOWN on the window that already has focus. Ensure no window received the
6338// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006339TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006341 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006342 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006344 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006345
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006346 ASSERT_TRUE(mDispatcher->waitForIdle());
6347 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006348}
6349
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006350// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6351// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6352TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6353 const MotionEvent event =
6354 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6355 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006356 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006357 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6358 .build();
6359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6361 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6362
6363 ASSERT_TRUE(mDispatcher->waitForIdle());
6364 mFakePolicy->assertOnPointerDownWasNotCalled();
6365 // Ensure that the unfocused window did not receive any FOCUS events.
6366 mUnfocusedWindow->assertNoEvents();
6367}
6368
chaviwaf87b3e2019-10-01 16:59:28 -07006369// These tests ensures we can send touch events to a single client when there are multiple input
6370// windows that point to the same client token.
6371class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6372 virtual void SetUp() override {
6373 InputDispatcherTest::SetUp();
6374
Chris Yea209fde2020-07-22 13:54:51 -07006375 std::shared_ptr<FakeApplicationHandle> application =
6376 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006377 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6378 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006379 mWindow1->setFrame(Rect(0, 0, 100, 100));
6380
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006381 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6382 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006383 mWindow2->setFrame(Rect(100, 100, 200, 200));
6384
Arthur Hung72d8dc32020-03-28 00:48:39 +00006385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006386 }
6387
6388protected:
6389 sp<FakeWindowHandle> mWindow1;
6390 sp<FakeWindowHandle> mWindow2;
6391
6392 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006393 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006394 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6395 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006396 }
6397
6398 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6399 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006400 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006401 InputEvent* event = window->consume();
6402
6403 ASSERT_NE(nullptr, event) << name.c_str()
6404 << ": consumer should have returned non-NULL event.";
6405
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006406 ASSERT_EQ(InputEventType::MOTION, event->getType())
6407 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006408
6409 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006410 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006411 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006412
6413 for (size_t i = 0; i < points.size(); i++) {
6414 float expectedX = points[i].x;
6415 float expectedY = points[i].y;
6416
6417 EXPECT_EQ(expectedX, motionEvent.getX(i))
6418 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6419 << ", got " << motionEvent.getX(i);
6420 EXPECT_EQ(expectedY, motionEvent.getY(i))
6421 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6422 << ", got " << motionEvent.getY(i);
6423 }
6424 }
chaviw9eaa22c2020-07-01 16:21:27 -07006425
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006426 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006427 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006428 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6429 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006430
6431 // Always consume from window1 since it's the window that has the InputReceiver
6432 consumeMotionEvent(mWindow1, action, expectedPoints);
6433 }
chaviwaf87b3e2019-10-01 16:59:28 -07006434};
6435
6436TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6437 // Touch Window 1
6438 PointF touchedPoint = {10, 10};
6439 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006440 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006441
6442 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006443 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006444
6445 // Touch Window 2
6446 touchedPoint = {150, 150};
6447 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006448 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006449}
6450
chaviw9eaa22c2020-07-01 16:21:27 -07006451TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6452 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006453 mWindow2->setWindowScale(0.5f, 0.5f);
6454
6455 // Touch Window 1
6456 PointF touchedPoint = {10, 10};
6457 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006458 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006459 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006460 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006461
6462 // Touch Window 2
6463 touchedPoint = {150, 150};
6464 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006465 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6466 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006467
chaviw9eaa22c2020-07-01 16:21:27 -07006468 // Update the transform so rotation is set
6469 mWindow2->setWindowTransform(0, -1, 1, 0);
6470 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6471 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006472}
6473
chaviw9eaa22c2020-07-01 16:21:27 -07006474TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006475 mWindow2->setWindowScale(0.5f, 0.5f);
6476
6477 // Touch Window 1
6478 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6479 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006480 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006481
6482 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006483 touchedPoints.push_back(PointF{150, 150});
6484 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006485 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006486
chaviw9eaa22c2020-07-01 16:21:27 -07006487 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006488 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006489 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006490
chaviw9eaa22c2020-07-01 16:21:27 -07006491 // Update the transform so rotation is set for Window 2
6492 mWindow2->setWindowTransform(0, -1, 1, 0);
6493 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006494 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006495}
6496
chaviw9eaa22c2020-07-01 16:21:27 -07006497TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006498 mWindow2->setWindowScale(0.5f, 0.5f);
6499
6500 // Touch Window 1
6501 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6502 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006503 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006504
6505 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006506 touchedPoints.push_back(PointF{150, 150});
6507 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006508
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006509 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006510
6511 // Move both windows
6512 touchedPoints = {{20, 20}, {175, 175}};
6513 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6514 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6515
chaviw9eaa22c2020-07-01 16:21:27 -07006516 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006517
chaviw9eaa22c2020-07-01 16:21:27 -07006518 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006519 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006520 expectedPoints.pop_back();
6521
6522 // Touch Window 2
6523 mWindow2->setWindowTransform(0, -1, 1, 0);
6524 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006525 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006526
6527 // Move both windows
6528 touchedPoints = {{20, 20}, {175, 175}};
6529 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6530 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6531
6532 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006533}
6534
6535TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6536 mWindow1->setWindowScale(0.5f, 0.5f);
6537
6538 // Touch Window 1
6539 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6540 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006541 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006542
6543 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006544 touchedPoints.push_back(PointF{150, 150});
6545 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006546
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006547 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006548
6549 // Move both windows
6550 touchedPoints = {{20, 20}, {175, 175}};
6551 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6552 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6553
chaviw9eaa22c2020-07-01 16:21:27 -07006554 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006555}
6556
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006557/**
6558 * When one of the windows is slippery, the touch should not slip into the other window with the
6559 * same input channel.
6560 */
6561TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6562 mWindow1->setSlippery(true);
6563 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6564
6565 // Touch down in window 1
6566 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6567 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6568 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6569
6570 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6571 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6572 // getting generated.
6573 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6574 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6575
6576 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6577}
6578
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006579/**
6580 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6581 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6582 * that the pointer is hovering over may have a different transform.
6583 */
6584TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6585 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6586
6587 // Start hover in window 1
6588 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6589 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6590 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6591 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6592
6593 // Move hover to window 2.
6594 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6595 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6596
6597 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6598 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6599 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6600}
6601
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006602class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6603 virtual void SetUp() override {
6604 InputDispatcherTest::SetUp();
6605
Chris Yea209fde2020-07-22 13:54:51 -07006606 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006607 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006608 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6609 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006610 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006611 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006612 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006613
6614 // Set focused application.
6615 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6616
6617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006618 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006619 mWindow->consumeFocusEvent(true);
6620 }
6621
6622 virtual void TearDown() override {
6623 InputDispatcherTest::TearDown();
6624 mWindow.clear();
6625 }
6626
6627protected:
Chris Yea209fde2020-07-22 13:54:51 -07006628 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006629 sp<FakeWindowHandle> mWindow;
6630 static constexpr PointF WINDOW_LOCATION = {20, 20};
6631
6632 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006634 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6635 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006637 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6638 WINDOW_LOCATION));
6639 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006640
6641 sp<FakeWindowHandle> addSpyWindow() {
6642 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006643 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006644 spy->setTrustedOverlay(true);
6645 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006646 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006647 spy->setDispatchingTimeout(30ms);
6648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6649 return spy;
6650 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006651};
6652
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006653// Send a tap and respond, which should not cause an ANR.
6654TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6655 tapOnWindow();
6656 mWindow->consumeMotionDown();
6657 mWindow->consumeMotionUp();
6658 ASSERT_TRUE(mDispatcher->waitForIdle());
6659 mFakePolicy->assertNotifyAnrWasNotCalled();
6660}
6661
6662// Send a regular key and respond, which should not cause an ANR.
6663TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006665 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6666 ASSERT_TRUE(mDispatcher->waitForIdle());
6667 mFakePolicy->assertNotifyAnrWasNotCalled();
6668}
6669
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006670TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6671 mWindow->setFocusable(false);
6672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6673 mWindow->consumeFocusEvent(false);
6674
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006675 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006676 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6677 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6678 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006680 // Key will not go to window because we have no focused window.
6681 // The 'no focused window' ANR timer should start instead.
6682
6683 // Now, the focused application goes away.
6684 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6685 // The key should get dropped and there should be no ANR.
6686
6687 ASSERT_TRUE(mDispatcher->waitForIdle());
6688 mFakePolicy->assertNotifyAnrWasNotCalled();
6689}
6690
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006691// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006692// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6693// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006694TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006696 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6697 WINDOW_LOCATION));
6698
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006699 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6700 ASSERT_TRUE(sequenceNum);
6701 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006702 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006703
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006704 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006705 mWindow->consumeMotionEvent(
6706 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006707 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006708 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006709}
6710
6711// Send a key to the app and have the app not respond right away.
6712TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6713 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006715 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6716 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006717 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006718 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006719 ASSERT_TRUE(mDispatcher->waitForIdle());
6720}
6721
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006722// We have a focused application, but no focused window
6723TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006724 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6726 mWindow->consumeFocusEvent(false);
6727
6728 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006730 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6731 WINDOW_LOCATION));
6732 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6733 mDispatcher->waitForIdle();
6734 mFakePolicy->assertNotifyAnrWasNotCalled();
6735
6736 // Once a focused event arrives, we get an ANR for this application
6737 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6738 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006739 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006740 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6741 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006742 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006743 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006744 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006745 ASSERT_TRUE(mDispatcher->waitForIdle());
6746}
6747
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006748/**
6749 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6750 * there will not be an ANR.
6751 */
6752TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6753 mWindow->setFocusable(false);
6754 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6755 mWindow->consumeFocusEvent(false);
6756
6757 KeyEvent event;
6758 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6759 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6760
6761 // Define a valid key down event that is stale (too old).
6762 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6763 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006764 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006765
6766 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6767
6768 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006769 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006770 InputEventInjectionSync::WAIT_FOR_RESULT,
6771 INJECT_EVENT_TIMEOUT, policyFlags);
6772 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6773 << "Injection should fail because the event is stale";
6774
6775 ASSERT_TRUE(mDispatcher->waitForIdle());
6776 mFakePolicy->assertNotifyAnrWasNotCalled();
6777 mWindow->assertNoEvents();
6778}
6779
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006780// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006781// Make sure that we don't notify policy twice about the same ANR.
6782TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006783 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6785 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006786
6787 // Once a focused event arrives, we get an ANR for this application
6788 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6789 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006790 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006791 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6792 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006793 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006794 const std::chrono::duration appTimeout =
6795 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6796 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006797
Vishnu Naire4df8752022-09-08 09:17:55 -07006798 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006799 // ANR should not be raised again. It is up to policy to do that if it desires.
6800 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006801
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006802 // If we now get a focused window, the ANR should stop, but the policy handles that via
6803 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006804 ASSERT_TRUE(mDispatcher->waitForIdle());
6805}
6806
6807// We have a focused application, but no focused window
6808TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006809 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6811 mWindow->consumeFocusEvent(false);
6812
6813 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006814 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006815 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006816 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6817 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006818
Vishnu Naire4df8752022-09-08 09:17:55 -07006819 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6820 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006821
6822 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006823 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006824 ASSERT_TRUE(mDispatcher->waitForIdle());
6825 mWindow->assertNoEvents();
6826}
6827
6828/**
6829 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6830 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6831 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6832 * the ANR mechanism should still work.
6833 *
6834 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6835 * DOWN event, while not responding on the second one.
6836 */
6837TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6838 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6839 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6840 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6841 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6842 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006843 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006844
6845 // Now send ACTION_UP, with identical timestamp
6846 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6847 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6848 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6849 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006850 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006851
6852 // We have now sent down and up. Let's consume first event and then ANR on the second.
6853 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6854 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006855 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006856}
6857
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006858// A spy window can receive an ANR
6859TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6860 sp<FakeWindowHandle> spy = addSpyWindow();
6861
6862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6863 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6864 WINDOW_LOCATION));
6865 mWindow->consumeMotionDown();
6866
6867 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6868 ASSERT_TRUE(sequenceNum);
6869 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006870 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006871
6872 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006873 spy->consumeMotionEvent(
6874 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006875 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006876 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006877}
6878
6879// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006880// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006881TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6882 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006883
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6885 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006886 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888
6889 // Stuck on the ACTION_UP
6890 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006891 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006892
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006893 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006894 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006895 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6896 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006897
6898 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6899 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006900 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006901 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006902 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006903}
6904
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006905// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006906// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006907TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6908 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006909
6910 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006911 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6912 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006913
6914 mWindow->consumeMotionDown();
6915 // Stuck on the ACTION_UP
6916 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006917 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006918
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006919 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006920 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006921 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6922 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006923
6924 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6925 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006926 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006927 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006928 spy->assertNoEvents();
6929}
6930
6931TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6932 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6933
6934 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6935
6936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6937 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6938 WINDOW_LOCATION));
6939
6940 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6941 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6942 ASSERT_TRUE(consumeSeq);
6943
Prabir Pradhanedd96402022-02-15 01:46:16 -08006944 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006945
6946 monitor.finishEvent(*consumeSeq);
6947 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6948
6949 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006950 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006951}
6952
6953// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6954// process events, you don't get an anr. When the window later becomes unresponsive again, you
6955// get an ANR again.
6956// 1. tap -> block on ACTION_UP -> receive ANR
6957// 2. consume all pending events (= queue becomes healthy again)
6958// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6959TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6960 tapOnWindow();
6961
6962 mWindow->consumeMotionDown();
6963 // Block on ACTION_UP
6964 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006965 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006966 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6967 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006968 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006969 mWindow->assertNoEvents();
6970
6971 tapOnWindow();
6972 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006973 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006974 mWindow->consumeMotionUp();
6975
6976 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006977 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006978 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006979 mWindow->assertNoEvents();
6980}
6981
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006982// If a connection remains unresponsive for a while, make sure policy is only notified once about
6983// it.
6984TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006986 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6987 WINDOW_LOCATION));
6988
6989 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006990 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006991 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006992 // 'notifyConnectionUnresponsive' should only be called once per connection
6993 mFakePolicy->assertNotifyAnrWasNotCalled();
6994 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006995 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006996 mWindow->consumeMotionEvent(
6997 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006998 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006999 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007000 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007001 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007002}
7003
7004/**
7005 * If a window is processing a motion event, and then a key event comes in, the key event should
7006 * not to to the focused window until the motion is processed.
7007 *
7008 * Warning!!!
7009 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7010 * and the injection timeout that we specify when injecting the key.
7011 * We must have the injection timeout (10ms) be smaller than
7012 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7013 *
7014 * If that value changes, this test should also change.
7015 */
7016TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7017 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7019
7020 tapOnWindow();
7021 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7022 ASSERT_TRUE(downSequenceNum);
7023 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7024 ASSERT_TRUE(upSequenceNum);
7025 // Don't finish the events yet, and send a key
7026 // Injection will "succeed" because we will eventually give up and send the key to the focused
7027 // window even if motions are still being processed. But because the injection timeout is short,
7028 // we will receive INJECTION_TIMED_OUT as the result.
7029
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007030 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007031 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007032 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7033 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007034 // Key will not be sent to the window, yet, because the window is still processing events
7035 // and the key remains pending, waiting for the touch events to be processed
7036 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7037 ASSERT_FALSE(keySequenceNum);
7038
7039 std::this_thread::sleep_for(500ms);
7040 // if we wait long enough though, dispatcher will give up, and still send the key
7041 // to the focused window, even though we have not yet finished the motion event
7042 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7043 mWindow->finishEvent(*downSequenceNum);
7044 mWindow->finishEvent(*upSequenceNum);
7045}
7046
7047/**
7048 * If a window is processing a motion event, and then a key event comes in, the key event should
7049 * not go to the focused window until the motion is processed.
7050 * If then a new motion comes in, then the pending key event should be going to the currently
7051 * focused window right away.
7052 */
7053TEST_F(InputDispatcherSingleWindowAnr,
7054 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7055 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7056 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7057
7058 tapOnWindow();
7059 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7060 ASSERT_TRUE(downSequenceNum);
7061 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7062 ASSERT_TRUE(upSequenceNum);
7063 // Don't finish the events yet, and send a key
7064 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007066 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7067 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007068 // At this point, key is still pending, and should not be sent to the application yet.
7069 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7070 ASSERT_FALSE(keySequenceNum);
7071
7072 // Now tap down again. It should cause the pending key to go to the focused window right away.
7073 tapOnWindow();
7074 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7075 // the other events yet. We can finish events in any order.
7076 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7077 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7078 mWindow->consumeMotionDown();
7079 mWindow->consumeMotionUp();
7080 mWindow->assertNoEvents();
7081}
7082
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007083/**
7084 * Send an event to the app and have the app not respond right away.
7085 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7086 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7087 * At some point, the window becomes responsive again.
7088 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7089 */
7090TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7092 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7093 .build());
7094
7095 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7096 ASSERT_TRUE(sequenceNum);
7097 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7098 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7099
7100 mWindow->finishEvent(*sequenceNum);
7101 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7102 ASSERT_TRUE(mDispatcher->waitForIdle());
7103 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7104
7105 // Now that the window is responsive, let's continue the gesture.
7106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7107 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7108 .build());
7109
7110 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7111 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7112 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7113 .build());
7114
7115 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7116 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7117 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7118 .build());
7119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7120 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7121 .build());
7122 // We already canceled this pointer, so the window shouldn't get any new events.
7123 mWindow->assertNoEvents();
7124
7125 // Start another one.
7126 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7127 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7128 .build());
7129 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7130}
7131
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007132class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7133 virtual void SetUp() override {
7134 InputDispatcherTest::SetUp();
7135
Chris Yea209fde2020-07-22 13:54:51 -07007136 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007137 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007138 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7139 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007140 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007141 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007142 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007143
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007144 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7145 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007146 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007147 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007148
7149 // Set focused application.
7150 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007151 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007152
7153 // Expect one focus window exist in display.
7154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007155 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007156 mFocusedWindow->consumeFocusEvent(true);
7157 }
7158
7159 virtual void TearDown() override {
7160 InputDispatcherTest::TearDown();
7161
7162 mUnfocusedWindow.clear();
7163 mFocusedWindow.clear();
7164 }
7165
7166protected:
Chris Yea209fde2020-07-22 13:54:51 -07007167 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007168 sp<FakeWindowHandle> mUnfocusedWindow;
7169 sp<FakeWindowHandle> mFocusedWindow;
7170 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7171 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7172 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7173
7174 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7175
7176 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7177
7178private:
7179 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007181 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7182 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007184 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7185 location));
7186 }
7187};
7188
7189// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7190// should be ANR'd first.
7191TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007193 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7194 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007196 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007197 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007198 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007199 // We consumed all events, so no ANR
7200 ASSERT_TRUE(mDispatcher->waitForIdle());
7201 mFakePolicy->assertNotifyAnrWasNotCalled();
7202
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007204 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7205 FOCUSED_WINDOW_LOCATION));
7206 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7207 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007208
7209 const std::chrono::duration timeout =
7210 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007211 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007212 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7213 // sequence to make it consistent
7214 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007215 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007216 mFocusedWindow->consumeMotionDown();
7217 // This cancel is generated because the connection was unresponsive
7218 mFocusedWindow->consumeMotionCancel();
7219 mFocusedWindow->assertNoEvents();
7220 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007221 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007222 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7223 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007224 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007225}
7226
7227// If we have 2 windows with identical timeouts that are both unresponsive,
7228// it doesn't matter which order they should have ANR.
7229// But we should receive ANR for both.
7230TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7231 // Set the timeout for unfocused window to match the focused window
7232 mUnfocusedWindow->setDispatchingTimeout(10ms);
7233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7234
7235 tapOnFocusedWindow();
7236 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007237 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7238 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7239 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007240
7241 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007242 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7243 mFocusedWindow->getToken() == anrConnectionToken2);
7244 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7245 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007246
7247 ASSERT_TRUE(mDispatcher->waitForIdle());
7248 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007249
7250 mFocusedWindow->consumeMotionDown();
7251 mFocusedWindow->consumeMotionUp();
7252 mUnfocusedWindow->consumeMotionOutside();
7253
Prabir Pradhanedd96402022-02-15 01:46:16 -08007254 sp<IBinder> responsiveToken1, responsiveToken2;
7255 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7256 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007257
7258 // Both applications should be marked as responsive, in any order
7259 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7260 mFocusedWindow->getToken() == responsiveToken2);
7261 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7262 mUnfocusedWindow->getToken() == responsiveToken2);
7263 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007264}
7265
7266// If a window is already not responding, the second tap on the same window should be ignored.
7267// We should also log an error to account for the dropped event (not tested here).
7268// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7269TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7270 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007271 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007272 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007273 // Receive the events, but don't respond
7274 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7275 ASSERT_TRUE(downEventSequenceNum);
7276 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7277 ASSERT_TRUE(upEventSequenceNum);
7278 const std::chrono::duration timeout =
7279 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007280 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007281
7282 // Tap once again
7283 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007284 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007285 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7286 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007287 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007288 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7289 FOCUSED_WINDOW_LOCATION));
7290 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7291 // valid touch target
7292 mUnfocusedWindow->assertNoEvents();
7293
7294 // Consume the first tap
7295 mFocusedWindow->finishEvent(*downEventSequenceNum);
7296 mFocusedWindow->finishEvent(*upEventSequenceNum);
7297 ASSERT_TRUE(mDispatcher->waitForIdle());
7298 // The second tap did not go to the focused window
7299 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007300 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007301 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7302 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007303 mFakePolicy->assertNotifyAnrWasNotCalled();
7304}
7305
7306// If you tap outside of all windows, there will not be ANR
7307TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007308 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007309 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7310 LOCATION_OUTSIDE_ALL_WINDOWS));
7311 ASSERT_TRUE(mDispatcher->waitForIdle());
7312 mFakePolicy->assertNotifyAnrWasNotCalled();
7313}
7314
7315// Since the focused window is paused, tapping on it should not produce any events
7316TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7317 mFocusedWindow->setPaused(true);
7318 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7319
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007320 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007321 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7322 FOCUSED_WINDOW_LOCATION));
7323
7324 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7325 ASSERT_TRUE(mDispatcher->waitForIdle());
7326 // Should not ANR because the window is paused, and touches shouldn't go to it
7327 mFakePolicy->assertNotifyAnrWasNotCalled();
7328
7329 mFocusedWindow->assertNoEvents();
7330 mUnfocusedWindow->assertNoEvents();
7331}
7332
7333/**
7334 * If a window is processing a motion event, and then a key event comes in, the key event should
7335 * not to to the focused window until the motion is processed.
7336 * If a different window becomes focused at this time, the key should go to that window instead.
7337 *
7338 * Warning!!!
7339 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7340 * and the injection timeout that we specify when injecting the key.
7341 * We must have the injection timeout (10ms) be smaller than
7342 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7343 *
7344 * If that value changes, this test should also change.
7345 */
7346TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7347 // Set a long ANR timeout to prevent it from triggering
7348 mFocusedWindow->setDispatchingTimeout(2s);
7349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7350
7351 tapOnUnfocusedWindow();
7352 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7353 ASSERT_TRUE(downSequenceNum);
7354 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7355 ASSERT_TRUE(upSequenceNum);
7356 // Don't finish the events yet, and send a key
7357 // Injection will succeed because we will eventually give up and send the key to the focused
7358 // window even if motions are still being processed.
7359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007360 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007361 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7362 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007364 // Key will not be sent to the window, yet, because the window is still processing events
7365 // and the key remains pending, waiting for the touch events to be processed
7366 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7367 ASSERT_FALSE(keySequenceNum);
7368
7369 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007370 mFocusedWindow->setFocusable(false);
7371 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007373 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007374
7375 // Focus events should precede the key events
7376 mUnfocusedWindow->consumeFocusEvent(true);
7377 mFocusedWindow->consumeFocusEvent(false);
7378
7379 // Finish the tap events, which should unblock dispatcher
7380 mUnfocusedWindow->finishEvent(*downSequenceNum);
7381 mUnfocusedWindow->finishEvent(*upSequenceNum);
7382
7383 // Now that all queues are cleared and no backlog in the connections, the key event
7384 // can finally go to the newly focused "mUnfocusedWindow".
7385 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7386 mFocusedWindow->assertNoEvents();
7387 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007388 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007389}
7390
7391// When the touch stream is split across 2 windows, and one of them does not respond,
7392// then ANR should be raised and the touch should be canceled for the unresponsive window.
7393// The other window should not be affected by that.
7394TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7395 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7397 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7398 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007399 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007400 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007401
7402 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007403 mDispatcher->notifyMotion(
7404 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7405 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007406
7407 const std::chrono::duration timeout =
7408 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007409 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007410
7411 mUnfocusedWindow->consumeMotionDown();
7412 mFocusedWindow->consumeMotionDown();
7413 // Focused window may or may not receive ACTION_MOVE
7414 // But it should definitely receive ACTION_CANCEL due to the ANR
7415 InputEvent* event;
7416 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7417 ASSERT_TRUE(moveOrCancelSequenceNum);
7418 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7419 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007420 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007421 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7422 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7423 mFocusedWindow->consumeMotionCancel();
7424 } else {
7425 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7426 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007427 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007428 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7429 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007430
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007431 mUnfocusedWindow->assertNoEvents();
7432 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007433 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434}
7435
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007436/**
7437 * If we have no focused window, and a key comes in, we start the ANR timer.
7438 * The focused application should add a focused window before the timer runs out to prevent ANR.
7439 *
7440 * If the user touches another application during this time, the key should be dropped.
7441 * Next, if a new focused window comes in, without toggling the focused application,
7442 * then no ANR should occur.
7443 *
7444 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7445 * but in some cases the policy may not update the focused application.
7446 */
7447TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7448 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7449 std::make_shared<FakeApplicationHandle>();
7450 focusedApplication->setDispatchingTimeout(60ms);
7451 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7452 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7453 mFocusedWindow->setFocusable(false);
7454
7455 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7456 mFocusedWindow->consumeFocusEvent(false);
7457
7458 // Send a key. The ANR timer should start because there is no focused window.
7459 // 'focusedApplication' will get blamed if this timer completes.
7460 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007461 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007462 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7463 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7464 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007466
7467 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7468 // then the injected touches won't cause the focused event to get dropped.
7469 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7470 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7471 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7472 // For this test, it means that the key would get delivered to the window once it becomes
7473 // focused.
7474 std::this_thread::sleep_for(10ms);
7475
7476 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007477 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7478 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7479 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007480
7481 // We do not consume the motion right away, because that would require dispatcher to first
7482 // process (== drop) the key event, and by that time, ANR will be raised.
7483 // Set the focused window first.
7484 mFocusedWindow->setFocusable(true);
7485 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7486 setFocusedWindow(mFocusedWindow);
7487 mFocusedWindow->consumeFocusEvent(true);
7488 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7489 // to another application. This could be a bug / behaviour in the policy.
7490
7491 mUnfocusedWindow->consumeMotionDown();
7492
7493 ASSERT_TRUE(mDispatcher->waitForIdle());
7494 // Should not ANR because we actually have a focused window. It was just added too slowly.
7495 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7496}
7497
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007498// These tests ensure we cannot send touch events to a window that's positioned behind a window
7499// that has feature NO_INPUT_CHANNEL.
7500// Layout:
7501// Top (closest to user)
7502// mNoInputWindow (above all windows)
7503// mBottomWindow
7504// Bottom (furthest from user)
7505class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7506 virtual void SetUp() override {
7507 InputDispatcherTest::SetUp();
7508
7509 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007510 mNoInputWindow =
7511 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7512 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007513 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007514 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007515 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7516 // It's perfectly valid for this window to not have an associated input channel
7517
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007518 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7519 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007520 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7521
7522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7523 }
7524
7525protected:
7526 std::shared_ptr<FakeApplicationHandle> mApplication;
7527 sp<FakeWindowHandle> mNoInputWindow;
7528 sp<FakeWindowHandle> mBottomWindow;
7529};
7530
7531TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7532 PointF touchedPoint = {10, 10};
7533
Prabir Pradhan678438e2023-04-13 19:32:51 +00007534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7536 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007537
7538 mNoInputWindow->assertNoEvents();
7539 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7540 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7541 // and therefore should prevent mBottomWindow from receiving touches
7542 mBottomWindow->assertNoEvents();
7543}
7544
7545/**
7546 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7547 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7548 */
7549TEST_F(InputDispatcherMultiWindowOcclusionTests,
7550 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007551 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7552 "Window with input channel and NO_INPUT_CHANNEL",
7553 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007554
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007555 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007556 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7557 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7558
7559 PointF touchedPoint = {10, 10};
7560
Prabir Pradhan678438e2023-04-13 19:32:51 +00007561 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7562 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7563 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007564
7565 mNoInputWindow->assertNoEvents();
7566 mBottomWindow->assertNoEvents();
7567}
7568
Vishnu Nair958da932020-08-21 17:12:37 -07007569class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7570protected:
7571 std::shared_ptr<FakeApplicationHandle> mApp;
7572 sp<FakeWindowHandle> mWindow;
7573 sp<FakeWindowHandle> mMirror;
7574
7575 virtual void SetUp() override {
7576 InputDispatcherTest::SetUp();
7577 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007578 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7579 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7580 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007581 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7582 mWindow->setFocusable(true);
7583 mMirror->setFocusable(true);
7584 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7585 }
7586};
7587
7588TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7589 // Request focus on a mirrored window
7590 setFocusedWindow(mMirror);
7591
7592 // window gets focused
7593 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7595 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007596 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7597}
7598
7599// A focused & mirrored window remains focused only if the window and its mirror are both
7600// focusable.
7601TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7602 setFocusedWindow(mMirror);
7603
7604 // window gets focused
7605 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7607 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007608 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7610 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007611 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7612
7613 mMirror->setFocusable(false);
7614 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7615
7616 // window loses focus since one of the windows associated with the token in not focusable
7617 mWindow->consumeFocusEvent(false);
7618
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007619 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7620 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007621 mWindow->assertNoEvents();
7622}
7623
7624// A focused & mirrored window remains focused until the window and its mirror both become
7625// invisible.
7626TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7627 setFocusedWindow(mMirror);
7628
7629 // window gets focused
7630 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7632 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007633 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7635 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007636 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7637
7638 mMirror->setVisible(false);
7639 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7640
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007643 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7645 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007646 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7647
7648 mWindow->setVisible(false);
7649 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7650
7651 // window loses focus only after all windows associated with the token become invisible.
7652 mWindow->consumeFocusEvent(false);
7653
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007654 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7655 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007656 mWindow->assertNoEvents();
7657}
7658
7659// A focused & mirrored window remains focused until both windows are removed.
7660TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7661 setFocusedWindow(mMirror);
7662
7663 // window gets focused
7664 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7666 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007667 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7669 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007670 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7671
7672 // single window is removed but the window token remains focused
7673 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7674
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7676 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007677 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7679 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007680 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7681
7682 // Both windows are removed
7683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7684 mWindow->consumeFocusEvent(false);
7685
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7687 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007688 mWindow->assertNoEvents();
7689}
7690
7691// Focus request can be pending until one window becomes visible.
7692TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7693 // Request focus on an invisible mirror.
7694 mWindow->setVisible(false);
7695 mMirror->setVisible(false);
7696 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7697 setFocusedWindow(mMirror);
7698
7699 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007701 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7702 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007703
7704 mMirror->setVisible(true);
7705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7706
7707 // window gets focused
7708 mWindow->consumeFocusEvent(true);
7709 // window gets the pending key event
7710 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7711}
Prabir Pradhan99987712020-11-10 18:43:05 -08007712
7713class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7714protected:
7715 std::shared_ptr<FakeApplicationHandle> mApp;
7716 sp<FakeWindowHandle> mWindow;
7717 sp<FakeWindowHandle> mSecondWindow;
7718
7719 void SetUp() override {
7720 InputDispatcherTest::SetUp();
7721 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007722 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007723 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007724 mSecondWindow =
7725 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007726 mSecondWindow->setFocusable(true);
7727
7728 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7729 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7730
7731 setFocusedWindow(mWindow);
7732 mWindow->consumeFocusEvent(true);
7733 }
7734
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007735 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007736 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007737 }
7738
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007739 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7740 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007741 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007742 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7743 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007744 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007745 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007746 }
7747};
7748
7749TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7750 // Ensure that capture cannot be obtained for unfocused windows.
7751 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7752 mFakePolicy->assertSetPointerCaptureNotCalled();
7753 mSecondWindow->assertNoEvents();
7754
7755 // Ensure that capture can be enabled from the focus window.
7756 requestAndVerifyPointerCapture(mWindow, true);
7757
7758 // Ensure that capture cannot be disabled from a window that does not have capture.
7759 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7760 mFakePolicy->assertSetPointerCaptureNotCalled();
7761
7762 // Ensure that capture can be disabled from the window with capture.
7763 requestAndVerifyPointerCapture(mWindow, false);
7764}
7765
7766TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007767 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007768
7769 setFocusedWindow(mSecondWindow);
7770
7771 // Ensure that the capture disabled event was sent first.
7772 mWindow->consumeCaptureEvent(false);
7773 mWindow->consumeFocusEvent(false);
7774 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007775 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007776
7777 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007778 notifyPointerCaptureChanged({});
7779 notifyPointerCaptureChanged(request);
7780 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007781 mWindow->assertNoEvents();
7782 mSecondWindow->assertNoEvents();
7783 mFakePolicy->assertSetPointerCaptureNotCalled();
7784}
7785
7786TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007787 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007788
7789 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007790 notifyPointerCaptureChanged({});
7791 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007792
7793 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007794 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007795 mWindow->consumeCaptureEvent(false);
7796 mWindow->assertNoEvents();
7797}
7798
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007799TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7800 requestAndVerifyPointerCapture(mWindow, true);
7801
7802 // The first window loses focus.
7803 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007804 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007805 mWindow->consumeCaptureEvent(false);
7806
7807 // Request Pointer Capture from the second window before the notification from InputReader
7808 // arrives.
7809 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007810 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007811
7812 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007813 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007814
7815 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007816 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007817
7818 mSecondWindow->consumeFocusEvent(true);
7819 mSecondWindow->consumeCaptureEvent(true);
7820}
7821
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007822TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7823 // App repeatedly enables and disables capture.
7824 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7825 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7826 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7827 mFakePolicy->assertSetPointerCaptureCalled(false);
7828 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7829 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7830
7831 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7832 // first request is now stale, this should do nothing.
7833 notifyPointerCaptureChanged(firstRequest);
7834 mWindow->assertNoEvents();
7835
7836 // InputReader notifies that the second request was enabled.
7837 notifyPointerCaptureChanged(secondRequest);
7838 mWindow->consumeCaptureEvent(true);
7839}
7840
Prabir Pradhan7092e262022-05-03 16:51:09 +00007841TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7842 requestAndVerifyPointerCapture(mWindow, true);
7843
7844 // App toggles pointer capture off and on.
7845 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7846 mFakePolicy->assertSetPointerCaptureCalled(false);
7847
7848 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7849 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7850
7851 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7852 // preceding "disable" request.
7853 notifyPointerCaptureChanged(enableRequest);
7854
7855 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7856 // any notifications.
7857 mWindow->assertNoEvents();
7858}
7859
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007860class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7861protected:
7862 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007863
7864 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7865 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7866
7867 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7868 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7869
7870 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7871 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7872 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7873 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7874 MAXIMUM_OBSCURING_OPACITY);
7875
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007876 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7877 static constexpr gui::Uid APP_B_UID{10002};
7878 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007879
7880 sp<FakeWindowHandle> mTouchWindow;
7881
7882 virtual void SetUp() override {
7883 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007884 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007885 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7886 }
7887
7888 virtual void TearDown() override {
7889 InputDispatcherTest::TearDown();
7890 mTouchWindow.clear();
7891 }
7892
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007893 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007894 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007895 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007896 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007897 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007898 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007899 return window;
7900 }
7901
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007902 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007903 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7904 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007905 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007906 // Generate an arbitrary PID based on the UID
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007907 window->setOwnerInfo(1777 + (uid.val() % 10000), uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007908 return window;
7909 }
7910
7911 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007912 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7913 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7914 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007915 }
7916};
7917
7918TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007919 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007920 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007922
7923 touch();
7924
7925 mTouchWindow->assertNoEvents();
7926}
7927
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007928TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007929 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7930 const sp<FakeWindowHandle>& w =
7931 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7933
7934 touch();
7935
7936 mTouchWindow->assertNoEvents();
7937}
7938
7939TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007940 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7941 const sp<FakeWindowHandle>& w =
7942 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7943 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7944
7945 touch();
7946
7947 w->assertNoEvents();
7948}
7949
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007950TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007951 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7952 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007953
7954 touch();
7955
7956 mTouchWindow->consumeAnyMotionDown();
7957}
7958
7959TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007960 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007961 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007962 w->setFrame(Rect(0, 0, 50, 50));
7963 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007964
7965 touch({PointF{100, 100}});
7966
7967 mTouchWindow->consumeAnyMotionDown();
7968}
7969
7970TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007971 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007972 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007973 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7974
7975 touch();
7976
7977 mTouchWindow->consumeAnyMotionDown();
7978}
7979
7980TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7981 const sp<FakeWindowHandle>& w =
7982 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007984
7985 touch();
7986
7987 mTouchWindow->consumeAnyMotionDown();
7988}
7989
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007990TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7991 const sp<FakeWindowHandle>& w =
7992 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7994
7995 touch();
7996
7997 w->assertNoEvents();
7998}
7999
8000/**
8001 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8002 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8003 * window, the occluding window will still receive ACTION_OUTSIDE event.
8004 */
8005TEST_F(InputDispatcherUntrustedTouchesTest,
8006 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8007 const sp<FakeWindowHandle>& w =
8008 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008009 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008010 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8011
8012 touch();
8013
8014 w->consumeMotionOutside();
8015}
8016
8017TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8018 const sp<FakeWindowHandle>& w =
8019 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008020 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008021 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8022
8023 touch();
8024
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008025 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008026}
8027
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008028TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008029 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008030 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8031 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008032 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8033
8034 touch();
8035
8036 mTouchWindow->consumeAnyMotionDown();
8037}
8038
8039TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8040 const sp<FakeWindowHandle>& w =
8041 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8042 MAXIMUM_OBSCURING_OPACITY);
8043 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008044
8045 touch();
8046
8047 mTouchWindow->consumeAnyMotionDown();
8048}
8049
8050TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008051 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008052 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8053 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008054 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8055
8056 touch();
8057
8058 mTouchWindow->assertNoEvents();
8059}
8060
8061TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8062 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8063 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008064 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8065 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008066 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008067 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8068 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008069 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8070
8071 touch();
8072
8073 mTouchWindow->assertNoEvents();
8074}
8075
8076TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8077 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8078 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008079 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8080 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008081 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008082 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8083 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008084 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8085
8086 touch();
8087
8088 mTouchWindow->consumeAnyMotionDown();
8089}
8090
8091TEST_F(InputDispatcherUntrustedTouchesTest,
8092 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8093 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008094 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8095 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008096 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008097 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8098 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8100
8101 touch();
8102
8103 mTouchWindow->consumeAnyMotionDown();
8104}
8105
8106TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8107 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008108 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8109 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008110 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008111 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8112 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008114
8115 touch();
8116
8117 mTouchWindow->assertNoEvents();
8118}
8119
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008120TEST_F(InputDispatcherUntrustedTouchesTest,
8121 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8122 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008123 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8124 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008125 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008126 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8127 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008128 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8129
8130 touch();
8131
8132 mTouchWindow->assertNoEvents();
8133}
8134
8135TEST_F(InputDispatcherUntrustedTouchesTest,
8136 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8137 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008138 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8139 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008140 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008141 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8142 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8144
8145 touch();
8146
8147 mTouchWindow->consumeAnyMotionDown();
8148}
8149
8150TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8151 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008152 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8153 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8155
8156 touch();
8157
8158 mTouchWindow->consumeAnyMotionDown();
8159}
8160
8161TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8162 const sp<FakeWindowHandle>& w =
8163 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8164 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8165
8166 touch();
8167
8168 mTouchWindow->consumeAnyMotionDown();
8169}
8170
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008171TEST_F(InputDispatcherUntrustedTouchesTest,
8172 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8173 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8174 const sp<FakeWindowHandle>& w =
8175 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8176 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8177
8178 touch();
8179
8180 mTouchWindow->assertNoEvents();
8181}
8182
8183TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8184 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8185 const sp<FakeWindowHandle>& w =
8186 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8188
8189 touch();
8190
8191 mTouchWindow->consumeAnyMotionDown();
8192}
8193
8194TEST_F(InputDispatcherUntrustedTouchesTest,
8195 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8196 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8197 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008198 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8199 OPACITY_ABOVE_THRESHOLD);
8200 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8201
8202 touch();
8203
8204 mTouchWindow->consumeAnyMotionDown();
8205}
8206
8207TEST_F(InputDispatcherUntrustedTouchesTest,
8208 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8209 const sp<FakeWindowHandle>& w1 =
8210 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8211 OPACITY_BELOW_THRESHOLD);
8212 const sp<FakeWindowHandle>& w2 =
8213 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8214 OPACITY_BELOW_THRESHOLD);
8215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8216
8217 touch();
8218
8219 mTouchWindow->assertNoEvents();
8220}
8221
8222/**
8223 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8224 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8225 * (which alone would result in allowing touches) does not affect the blocking behavior.
8226 */
8227TEST_F(InputDispatcherUntrustedTouchesTest,
8228 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8229 const sp<FakeWindowHandle>& wB =
8230 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8231 OPACITY_BELOW_THRESHOLD);
8232 const sp<FakeWindowHandle>& wC =
8233 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8234 OPACITY_BELOW_THRESHOLD);
8235 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8236
8237 touch();
8238
8239 mTouchWindow->assertNoEvents();
8240}
8241
8242/**
8243 * This test is testing that a window from a different UID but with same application token doesn't
8244 * block the touch. Apps can share the application token for close UI collaboration for example.
8245 */
8246TEST_F(InputDispatcherUntrustedTouchesTest,
8247 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8248 const sp<FakeWindowHandle>& w =
8249 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8250 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8252
8253 touch();
8254
8255 mTouchWindow->consumeAnyMotionDown();
8256}
8257
arthurhungb89ccb02020-12-30 16:19:01 +08008258class InputDispatcherDragTests : public InputDispatcherTest {
8259protected:
8260 std::shared_ptr<FakeApplicationHandle> mApp;
8261 sp<FakeWindowHandle> mWindow;
8262 sp<FakeWindowHandle> mSecondWindow;
8263 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008264 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008265 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8266 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008267
8268 void SetUp() override {
8269 InputDispatcherTest::SetUp();
8270 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008271 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008272 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008273
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008274 mSecondWindow =
8275 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008276 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008277
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008278 mSpyWindow =
8279 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008280 mSpyWindow->setSpy(true);
8281 mSpyWindow->setTrustedOverlay(true);
8282 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8283
arthurhungb89ccb02020-12-30 16:19:01 +08008284 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008285 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008286 }
8287
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008288 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8289 switch (fromSource) {
8290 case AINPUT_SOURCE_TOUCHSCREEN:
8291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8292 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8293 ADISPLAY_ID_DEFAULT, {50, 50}))
8294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8295 break;
8296 case AINPUT_SOURCE_STYLUS:
8297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8298 injectMotionEvent(
8299 mDispatcher,
8300 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8301 AINPUT_SOURCE_STYLUS)
8302 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008303 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008304 .x(50)
8305 .y(50))
8306 .build()));
8307 break;
8308 case AINPUT_SOURCE_MOUSE:
8309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8310 injectMotionEvent(
8311 mDispatcher,
8312 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8313 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8314 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008315 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008316 .x(50)
8317 .y(50))
8318 .build()));
8319 break;
8320 default:
8321 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8322 }
arthurhungb89ccb02020-12-30 16:19:01 +08008323
8324 // Window should receive motion event.
8325 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008326 // Spy window should also receive motion event
8327 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008328 }
8329
8330 // Start performing drag, we will create a drag window and transfer touch to it.
8331 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8332 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008333 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008334 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008335 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008336 }
arthurhungb89ccb02020-12-30 16:19:01 +08008337
8338 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008339 mDragWindow =
8340 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008341 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008342 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008343 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008344
8345 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008346 bool transferred =
8347 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008348 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008349 if (transferred) {
8350 mWindow->consumeMotionCancel();
8351 mDragWindow->consumeMotionDown();
8352 }
8353 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008354 }
8355};
8356
8357TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008358 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008359
8360 // Move on window.
8361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8362 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8363 ADISPLAY_ID_DEFAULT, {50, 50}))
8364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8365 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8366 mWindow->consumeDragEvent(false, 50, 50);
8367 mSecondWindow->assertNoEvents();
8368
8369 // Move to another window.
8370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8371 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8372 ADISPLAY_ID_DEFAULT, {150, 50}))
8373 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8374 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8375 mWindow->consumeDragEvent(true, 150, 50);
8376 mSecondWindow->consumeDragEvent(false, 50, 50);
8377
8378 // Move back to original window.
8379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8380 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8381 ADISPLAY_ID_DEFAULT, {50, 50}))
8382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8383 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8384 mWindow->consumeDragEvent(false, 50, 50);
8385 mSecondWindow->consumeDragEvent(true, -50, 50);
8386
8387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8388 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8389 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8390 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8391 mWindow->assertNoEvents();
8392 mSecondWindow->assertNoEvents();
8393}
8394
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008395TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008396 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008397
8398 // No cancel event after drag start
8399 mSpyWindow->assertNoEvents();
8400
8401 const MotionEvent secondFingerDownEvent =
8402 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8403 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008404 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8405 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008406 .build();
8407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8408 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8409 InputEventInjectionSync::WAIT_FOR_RESULT))
8410 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8411
8412 // Receives cancel for first pointer after next pointer down
8413 mSpyWindow->consumeMotionCancel();
8414 mSpyWindow->consumeMotionDown();
8415
8416 mSpyWindow->assertNoEvents();
8417}
8418
arthurhungf452d0b2021-01-06 00:19:52 +08008419TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008420 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008421
8422 // Move on window.
8423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8424 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8425 ADISPLAY_ID_DEFAULT, {50, 50}))
8426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8427 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8428 mWindow->consumeDragEvent(false, 50, 50);
8429 mSecondWindow->assertNoEvents();
8430
8431 // Move to another window.
8432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8433 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8434 ADISPLAY_ID_DEFAULT, {150, 50}))
8435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8436 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8437 mWindow->consumeDragEvent(true, 150, 50);
8438 mSecondWindow->consumeDragEvent(false, 50, 50);
8439
8440 // drop to another window.
8441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8442 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8443 {150, 50}))
8444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8445 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8446 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8447 mWindow->assertNoEvents();
8448 mSecondWindow->assertNoEvents();
8449}
8450
arthurhung6d4bed92021-03-17 11:59:33 +08008451TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008452 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008453
8454 // Move on window and keep button pressed.
8455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8456 injectMotionEvent(mDispatcher,
8457 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8458 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008459 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008460 .build()))
8461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8462 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8463 mWindow->consumeDragEvent(false, 50, 50);
8464 mSecondWindow->assertNoEvents();
8465
8466 // Move to another window and release button, expect to drop item.
8467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8468 injectMotionEvent(mDispatcher,
8469 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8470 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008471 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008472 .build()))
8473 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8474 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8475 mWindow->assertNoEvents();
8476 mSecondWindow->assertNoEvents();
8477 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8478
8479 // nothing to the window.
8480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8481 injectMotionEvent(mDispatcher,
8482 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8483 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008484 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008485 .build()))
8486 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8487 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8488 mWindow->assertNoEvents();
8489 mSecondWindow->assertNoEvents();
8490}
8491
Arthur Hung54745652022-04-20 07:17:41 +00008492TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008493 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008494
8495 // Set second window invisible.
8496 mSecondWindow->setVisible(false);
8497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8498
8499 // Move on window.
8500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8501 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8502 ADISPLAY_ID_DEFAULT, {50, 50}))
8503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8504 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8505 mWindow->consumeDragEvent(false, 50, 50);
8506 mSecondWindow->assertNoEvents();
8507
8508 // Move to another window.
8509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8510 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8511 ADISPLAY_ID_DEFAULT, {150, 50}))
8512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8513 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8514 mWindow->consumeDragEvent(true, 150, 50);
8515 mSecondWindow->assertNoEvents();
8516
8517 // drop to another window.
8518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8519 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8520 {150, 50}))
8521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8522 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8523 mFakePolicy->assertDropTargetEquals(nullptr);
8524 mWindow->assertNoEvents();
8525 mSecondWindow->assertNoEvents();
8526}
8527
Arthur Hung54745652022-04-20 07:17:41 +00008528TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008529 // Ensure window could track pointerIds if it didn't support split touch.
8530 mWindow->setPreventSplitting(true);
8531
Arthur Hung54745652022-04-20 07:17:41 +00008532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8533 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8534 {50, 50}))
8535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8536 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8537
8538 const MotionEvent secondFingerDownEvent =
8539 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8540 .displayId(ADISPLAY_ID_DEFAULT)
8541 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008542 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8543 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008544 .build();
8545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8546 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8547 InputEventInjectionSync::WAIT_FOR_RESULT))
8548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008549 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008550
8551 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008552 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008553}
8554
8555TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8556 // First down on second window.
8557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8558 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8559 {150, 50}))
8560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8561
8562 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8563
8564 // Second down on first window.
8565 const MotionEvent secondFingerDownEvent =
8566 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8567 .displayId(ADISPLAY_ID_DEFAULT)
8568 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008569 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8570 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008571 .build();
8572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8573 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8574 InputEventInjectionSync::WAIT_FOR_RESULT))
8575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8576 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8577
8578 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008579 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008580
8581 // Move on window.
8582 const MotionEvent secondFingerMoveEvent =
8583 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8584 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008585 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8586 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008587 .build();
8588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8589 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8590 InputEventInjectionSync::WAIT_FOR_RESULT));
8591 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8592 mWindow->consumeDragEvent(false, 50, 50);
8593 mSecondWindow->consumeMotionMove();
8594
8595 // Release the drag pointer should perform drop.
8596 const MotionEvent secondFingerUpEvent =
8597 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8598 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008599 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8600 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008601 .build();
8602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8603 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8604 InputEventInjectionSync::WAIT_FOR_RESULT));
8605 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8606 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8607 mWindow->assertNoEvents();
8608 mSecondWindow->consumeMotionMove();
8609}
8610
Arthur Hung3915c1f2022-05-31 07:17:17 +00008611TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008612 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008613
8614 // Update window of second display.
8615 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008616 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008617 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8618
8619 // Let second display has a touch state.
8620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8621 injectMotionEvent(mDispatcher,
8622 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8623 AINPUT_SOURCE_TOUCHSCREEN)
8624 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008625 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008626 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008627 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008628 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008629 // Update window again.
8630 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8631
8632 // Move on window.
8633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8634 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8635 ADISPLAY_ID_DEFAULT, {50, 50}))
8636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8637 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8638 mWindow->consumeDragEvent(false, 50, 50);
8639 mSecondWindow->assertNoEvents();
8640
8641 // Move to another window.
8642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8643 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8644 ADISPLAY_ID_DEFAULT, {150, 50}))
8645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8646 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8647 mWindow->consumeDragEvent(true, 150, 50);
8648 mSecondWindow->consumeDragEvent(false, 50, 50);
8649
8650 // drop to another window.
8651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8652 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8653 {150, 50}))
8654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8655 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8656 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8657 mWindow->assertNoEvents();
8658 mSecondWindow->assertNoEvents();
8659}
8660
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008661TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8662 startDrag(true, AINPUT_SOURCE_MOUSE);
8663 // Move on window.
8664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8665 injectMotionEvent(mDispatcher,
8666 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8667 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8668 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008669 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008670 .x(50)
8671 .y(50))
8672 .build()))
8673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8674 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8675 mWindow->consumeDragEvent(false, 50, 50);
8676 mSecondWindow->assertNoEvents();
8677
8678 // Move to another window.
8679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8680 injectMotionEvent(mDispatcher,
8681 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8682 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8683 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008684 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008685 .x(150)
8686 .y(50))
8687 .build()))
8688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8689 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8690 mWindow->consumeDragEvent(true, 150, 50);
8691 mSecondWindow->consumeDragEvent(false, 50, 50);
8692
8693 // drop to another window.
8694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8695 injectMotionEvent(mDispatcher,
8696 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8697 .buttonState(0)
8698 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008699 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008700 .x(150)
8701 .y(50))
8702 .build()))
8703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8704 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8705 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8706 mWindow->assertNoEvents();
8707 mSecondWindow->assertNoEvents();
8708}
8709
Vishnu Nair062a8672021-09-03 16:07:44 -07008710class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8711
8712TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8715 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008716 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008717 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8718 window->setFocusable(true);
8719 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8720 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008721 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008722
8723 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008724 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008725 window->assertNoEvents();
8726
Prabir Pradhan678438e2023-04-13 19:32:51 +00008727 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8728 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008729 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8730 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008731 window->assertNoEvents();
8732
8733 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008734 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8736
Prabir Pradhan678438e2023-04-13 19:32:51 +00008737 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008738 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8739
Prabir Pradhan678438e2023-04-13 19:32:51 +00008740 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8741 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008742 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8743 window->assertNoEvents();
8744}
8745
8746TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8747 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8748 std::make_shared<FakeApplicationHandle>();
8749 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008750 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8751 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008752 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008753 obscuringWindow->setOwnerInfo(111, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008754 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008756 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8757 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008758 window->setDropInputIfObscured(true);
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008759 window->setOwnerInfo(222, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008760 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8761 window->setFocusable(true);
8762 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8763 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008764 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008765
8766 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008767 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008768 window->assertNoEvents();
8769
Prabir Pradhan678438e2023-04-13 19:32:51 +00008770 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8771 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8773 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008774 window->assertNoEvents();
8775
8776 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008777 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8779
Prabir Pradhan678438e2023-04-13 19:32:51 +00008780 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008781 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8782
Prabir Pradhan678438e2023-04-13 19:32:51 +00008783 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8784 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008785 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8786 window->assertNoEvents();
8787}
8788
8789TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8790 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8791 std::make_shared<FakeApplicationHandle>();
8792 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008793 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8794 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008795 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008796 obscuringWindow->setOwnerInfo(111, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008797 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008799 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8800 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008801 window->setDropInputIfObscured(true);
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008802 window->setOwnerInfo(222, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008803 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8804 window->setFocusable(true);
8805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8806 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008807 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008808
8809 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008810 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008811 window->assertNoEvents();
8812
Prabir Pradhan678438e2023-04-13 19:32:51 +00008813 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8814 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008815 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8816 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008817 window->assertNoEvents();
8818
8819 // When the window is no longer obscured because it went on top, it should get input
8820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8821
Prabir Pradhan678438e2023-04-13 19:32:51 +00008822 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008823 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8824
Prabir Pradhan678438e2023-04-13 19:32:51 +00008825 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8826 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008827 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8828 window->assertNoEvents();
8829}
8830
Antonio Kantekf16f2832021-09-28 04:39:20 +00008831class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8832protected:
8833 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008834 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008835 sp<FakeWindowHandle> mWindow;
8836 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008837 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008838
8839 void SetUp() override {
8840 InputDispatcherTest::SetUp();
8841
8842 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008843 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008844 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008845 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008846 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008847 mSecondWindow =
8848 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008849 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008850 mThirdWindow =
8851 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8852 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8853 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008854
8855 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8857 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8858 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008859 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008860
Antonio Kantek15beb512022-06-13 22:35:41 +00008861 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008862 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008863 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008864 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8865 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008866 mThirdWindow->assertNoEvents();
8867 }
8868
8869 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8870 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008871 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008872 SECOND_DISPLAY_ID)) {
8873 mWindow->assertNoEvents();
8874 mSecondWindow->assertNoEvents();
8875 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008876 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008877 }
8878
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008879 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008880 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008881 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8882 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008883 mWindow->consumeTouchModeEvent(inTouchMode);
8884 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008885 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008886 }
8887};
8888
Antonio Kantek26defcf2022-02-08 01:12:27 +00008889TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008890 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008891 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8892 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008893 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008894}
8895
Antonio Kantek26defcf2022-02-08 01:12:27 +00008896TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8897 const WindowInfo& windowInfo = *mWindow->getInfo();
8898 int32_t ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008899 gui::Uid ownerUid = windowInfo.ownerUid;
8900 mWindow->setOwnerInfo(/*pid=*/-1, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008901 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008902 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008903 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008904 mWindow->assertNoEvents();
8905 mSecondWindow->assertNoEvents();
8906}
8907
8908TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8909 const WindowInfo& windowInfo = *mWindow->getInfo();
8910 int32_t ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008911 gui::Uid ownerUid = windowInfo.ownerUid;
8912 mWindow->setOwnerInfo(/*pid=*/-1, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008913 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008914 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008915}
8916
Antonio Kantekf16f2832021-09-28 04:39:20 +00008917TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008918 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008919 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8920 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008921 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008922 mWindow->assertNoEvents();
8923 mSecondWindow->assertNoEvents();
8924}
8925
Antonio Kantek15beb512022-06-13 22:35:41 +00008926TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8927 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8928 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8929 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008930 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008931 mWindow->assertNoEvents();
8932 mSecondWindow->assertNoEvents();
8933 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8934}
8935
Antonio Kantek48710e42022-03-24 14:19:30 -07008936TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8937 // Interact with the window first.
8938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8939 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8940 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8941
8942 // Then remove focus.
8943 mWindow->setFocusable(false);
8944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8945
8946 // Assert that caller can switch touch mode by owning one of the last interacted window.
8947 const WindowInfo& windowInfo = *mWindow->getInfo();
8948 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8949 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008950 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008951}
8952
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008953class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8954public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008955 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008956 std::shared_ptr<FakeApplicationHandle> application =
8957 std::make_shared<FakeApplicationHandle>();
8958 std::string name = "Fake Spy ";
8959 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008960 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8961 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008962 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008963 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008964 return spy;
8965 }
8966
8967 sp<FakeWindowHandle> createForeground() {
8968 std::shared_ptr<FakeApplicationHandle> application =
8969 std::make_shared<FakeApplicationHandle>();
8970 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008971 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8972 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008973 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008974 return window;
8975 }
8976
8977private:
8978 int mSpyCount{0};
8979};
8980
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008981using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008982/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008983 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8984 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008985TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8986 ScopedSilentDeath _silentDeath;
8987
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008988 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008989 spy->setTrustedOverlay(false);
8990 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8991 ".* not a trusted overlay");
8992}
8993
8994/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008995 * Input injection into a display with a spy window but no foreground windows should succeed.
8996 */
8997TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008998 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008999 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9000
9001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9002 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9004 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9005}
9006
9007/**
9008 * Verify the order in which different input windows receive events. The touched foreground window
9009 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9010 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9011 * receive events before ones belows it.
9012 *
9013 * Here, we set up a scenario with four windows in the following Z order from the top:
9014 * spy1, spy2, window, spy3.
9015 * We then inject an event and verify that the foreground "window" receives it first, followed by
9016 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9017 * window.
9018 */
9019TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9020 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009021 auto spy1 = createSpy();
9022 auto spy2 = createSpy();
9023 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9025 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9026 const size_t numChannels = channels.size();
9027
Michael Wright8e9a8562022-02-09 13:44:29 +00009028 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009029 if (!epollFd.ok()) {
9030 FAIL() << "Failed to create epoll fd";
9031 }
9032
9033 for (size_t i = 0; i < numChannels; i++) {
9034 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9035 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9036 FAIL() << "Failed to add fd to epoll";
9037 }
9038 }
9039
9040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9041 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9043
9044 std::vector<size_t> eventOrder;
9045 std::vector<struct epoll_event> events(numChannels);
9046 for (;;) {
9047 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9048 (100ms).count());
9049 if (nFds < 0) {
9050 FAIL() << "Failed to call epoll_wait";
9051 }
9052 if (nFds == 0) {
9053 break; // epoll_wait timed out
9054 }
9055 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009056 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009057 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009058 channels[i]->consumeMotionDown();
9059 }
9060 }
9061
9062 // Verify the order in which the events were received.
9063 EXPECT_EQ(3u, eventOrder.size());
9064 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9065 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9066 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9067}
9068
9069/**
9070 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9071 */
9072TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9073 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009074 auto spy = createSpy();
9075 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009076 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9077
9078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9079 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9081 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9082 spy->assertNoEvents();
9083}
9084
9085/**
9086 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9087 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9088 * to the window.
9089 */
9090TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9091 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009092 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009093 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9094 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9095
9096 // Inject an event outside the spy window's touchable region.
9097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9098 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9100 window->consumeMotionDown();
9101 spy->assertNoEvents();
9102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9103 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9105 window->consumeMotionUp();
9106 spy->assertNoEvents();
9107
9108 // Inject an event inside the spy window's touchable region.
9109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9111 {5, 10}))
9112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9113 window->consumeMotionDown();
9114 spy->consumeMotionDown();
9115}
9116
9117/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009118 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009119 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009120 */
9121TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9122 auto window = createForeground();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009123 window->setOwnerInfo(12, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009124 auto spy = createSpy();
9125 spy->setWatchOutsideTouch(true);
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009126 spy->setOwnerInfo(56, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009127 spy->setFrame(Rect{0, 0, 20, 20});
9128 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9129
9130 // Inject an event outside the spy window's frame and touchable region.
9131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009132 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9133 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009134 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9135 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009136 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009137}
9138
9139/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009140 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9141 * pointers that are down within its bounds.
9142 */
9143TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9144 auto windowLeft = createForeground();
9145 windowLeft->setFrame({0, 0, 100, 200});
9146 auto windowRight = createForeground();
9147 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009148 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009149 spy->setFrame({0, 0, 200, 200});
9150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9151
9152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9153 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9154 {50, 50}))
9155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9156 windowLeft->consumeMotionDown();
9157 spy->consumeMotionDown();
9158
9159 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009160 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009161 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009162 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9163 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009164 .build();
9165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9166 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9167 InputEventInjectionSync::WAIT_FOR_RESULT))
9168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9169 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009170 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009171}
9172
9173/**
9174 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9175 * the spy should receive the second pointer with ACTION_DOWN.
9176 */
9177TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9178 auto window = createForeground();
9179 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009180 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009181 spyRight->setFrame({100, 0, 200, 200});
9182 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9183
9184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9185 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9186 {50, 50}))
9187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9188 window->consumeMotionDown();
9189 spyRight->assertNoEvents();
9190
9191 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009192 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009193 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9195 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009196 .build();
9197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9198 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9199 InputEventInjectionSync::WAIT_FOR_RESULT))
9200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009201 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009202 spyRight->consumeMotionDown();
9203}
9204
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009205/**
9206 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9207 * windows should be allowed to control split touch.
9208 */
9209TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009210 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009211 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009212 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009213 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009214
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009215 auto window = createForeground();
9216 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009217
9218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9219
9220 // First finger down, no window touched.
9221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9222 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9223 {100, 200}))
9224 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9225 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9226 window->assertNoEvents();
9227
9228 // Second finger down on window, the window should receive touch down.
9229 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009230 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009231 .displayId(ADISPLAY_ID_DEFAULT)
9232 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009233 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9234 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009235 .build();
9236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9237 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9238 InputEventInjectionSync::WAIT_FOR_RESULT))
9239 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9240
9241 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009242 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009243}
9244
9245/**
9246 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9247 * do not receive key events.
9248 */
9249TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009250 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009251 spy->setFocusable(false);
9252
9253 auto window = createForeground();
9254 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9255 setFocusedWindow(window);
9256 window->consumeFocusEvent(true);
9257
9258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9259 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9260 window->consumeKeyDown(ADISPLAY_ID_NONE);
9261
9262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9263 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9264 window->consumeKeyUp(ADISPLAY_ID_NONE);
9265
9266 spy->assertNoEvents();
9267}
9268
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009269using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9270
9271/**
9272 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9273 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9274 */
9275TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9276 auto window = createForeground();
9277 auto spy1 = createSpy();
9278 auto spy2 = createSpy();
9279 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9280
9281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9282 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9284 window->consumeMotionDown();
9285 spy1->consumeMotionDown();
9286 spy2->consumeMotionDown();
9287
9288 // Pilfer pointers from the second spy window.
9289 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9290 spy2->assertNoEvents();
9291 spy1->consumeMotionCancel();
9292 window->consumeMotionCancel();
9293
9294 // The rest of the gesture should only be sent to the second spy window.
9295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9296 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9297 ADISPLAY_ID_DEFAULT))
9298 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9299 spy2->consumeMotionMove();
9300 spy1->assertNoEvents();
9301 window->assertNoEvents();
9302}
9303
9304/**
9305 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9306 * in the middle of the gesture.
9307 */
9308TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9309 auto window = createForeground();
9310 auto spy = createSpy();
9311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9312
9313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9314 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9316 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9317 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9318
9319 window->releaseChannel();
9320
9321 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9322
9323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9324 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9326 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9327}
9328
9329/**
9330 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9331 * the spy, but not to any other windows.
9332 */
9333TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9334 auto spy = createSpy();
9335 auto window = createForeground();
9336
9337 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9338
9339 // First finger down on the window and the spy.
9340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9341 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9342 {100, 200}))
9343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9344 spy->consumeMotionDown();
9345 window->consumeMotionDown();
9346
9347 // Spy window pilfers the pointers.
9348 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9349 window->consumeMotionCancel();
9350
9351 // Second finger down on the window and spy, but the window should not receive the pointer down.
9352 const MotionEvent secondFingerDownEvent =
9353 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9354 .displayId(ADISPLAY_ID_DEFAULT)
9355 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009356 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9357 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009358 .build();
9359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9360 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9361 InputEventInjectionSync::WAIT_FOR_RESULT))
9362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9363
Harry Cutts33476232023-01-30 19:57:29 +00009364 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009365
9366 // Third finger goes down outside all windows, so injection should fail.
9367 const MotionEvent thirdFingerDownEvent =
9368 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9369 .displayId(ADISPLAY_ID_DEFAULT)
9370 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009371 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9372 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9373 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009374 .build();
9375 ASSERT_EQ(InputEventInjectionResult::FAILED,
9376 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9377 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009378 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009379
9380 spy->assertNoEvents();
9381 window->assertNoEvents();
9382}
9383
9384/**
9385 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9386 */
9387TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9388 auto spy = createSpy();
9389 spy->setFrame(Rect(0, 0, 100, 100));
9390 auto window = createForeground();
9391 window->setFrame(Rect(0, 0, 200, 200));
9392
9393 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9394
9395 // First finger down on the window only
9396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9397 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9398 {150, 150}))
9399 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9400 window->consumeMotionDown();
9401
9402 // Second finger down on the spy and window
9403 const MotionEvent secondFingerDownEvent =
9404 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9405 .displayId(ADISPLAY_ID_DEFAULT)
9406 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009407 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9408 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009409 .build();
9410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9411 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9412 InputEventInjectionSync::WAIT_FOR_RESULT))
9413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9414 spy->consumeMotionDown();
9415 window->consumeMotionPointerDown(1);
9416
9417 // Third finger down on the spy and window
9418 const MotionEvent thirdFingerDownEvent =
9419 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9420 .displayId(ADISPLAY_ID_DEFAULT)
9421 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009422 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9423 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9424 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009425 .build();
9426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9427 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9428 InputEventInjectionSync::WAIT_FOR_RESULT))
9429 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9430 spy->consumeMotionPointerDown(1);
9431 window->consumeMotionPointerDown(2);
9432
9433 // Spy window pilfers the pointers.
9434 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9435 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9436 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9437
9438 spy->assertNoEvents();
9439 window->assertNoEvents();
9440}
9441
9442/**
9443 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9444 * other windows should be canceled. If this results in the cancellation of all pointers for some
9445 * window, then that window should receive ACTION_CANCEL.
9446 */
9447TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9448 auto spy = createSpy();
9449 spy->setFrame(Rect(0, 0, 100, 100));
9450 auto window = createForeground();
9451 window->setFrame(Rect(0, 0, 200, 200));
9452
9453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9454
9455 // First finger down on both spy and window
9456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9457 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9458 {10, 10}))
9459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9460 window->consumeMotionDown();
9461 spy->consumeMotionDown();
9462
9463 // Second finger down on the spy and window
9464 const MotionEvent secondFingerDownEvent =
9465 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9466 .displayId(ADISPLAY_ID_DEFAULT)
9467 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009468 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9469 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009470 .build();
9471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9472 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9473 InputEventInjectionSync::WAIT_FOR_RESULT))
9474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9475 spy->consumeMotionPointerDown(1);
9476 window->consumeMotionPointerDown(1);
9477
9478 // Spy window pilfers the pointers.
9479 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9480 window->consumeMotionCancel();
9481
9482 spy->assertNoEvents();
9483 window->assertNoEvents();
9484}
9485
9486/**
9487 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9488 * be sent to other windows
9489 */
9490TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9491 auto spy = createSpy();
9492 spy->setFrame(Rect(0, 0, 100, 100));
9493 auto window = createForeground();
9494 window->setFrame(Rect(0, 0, 200, 200));
9495
9496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9497
9498 // First finger down on both window and spy
9499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9500 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9501 {10, 10}))
9502 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9503 window->consumeMotionDown();
9504 spy->consumeMotionDown();
9505
9506 // Spy window pilfers the pointers.
9507 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9508 window->consumeMotionCancel();
9509
9510 // Second finger down on the window only
9511 const MotionEvent secondFingerDownEvent =
9512 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9513 .displayId(ADISPLAY_ID_DEFAULT)
9514 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009515 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9516 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009517 .build();
9518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9519 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9520 InputEventInjectionSync::WAIT_FOR_RESULT))
9521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9522 window->consumeMotionDown();
9523 window->assertNoEvents();
9524
9525 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9526 spy->consumeMotionMove();
9527 spy->assertNoEvents();
9528}
9529
Prabir Pradhand65552b2021-10-07 11:23:50 -07009530class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9531public:
9532 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9533 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9534 std::make_shared<FakeApplicationHandle>();
9535 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009536 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9537 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009538 overlay->setFocusable(false);
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009539 overlay->setOwnerInfo(111, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009540 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009541 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009542 overlay->setTrustedOverlay(true);
9543
9544 std::shared_ptr<FakeApplicationHandle> application =
9545 std::make_shared<FakeApplicationHandle>();
9546 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009547 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9548 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009549 window->setFocusable(true);
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009550 window->setOwnerInfo(222, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009551
9552 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9554 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009555 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009556 return {std::move(overlay), std::move(window)};
9557 }
9558
9559 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009560 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009561 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009562 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009563 }
9564
9565 void sendStylusEvent(int32_t action) {
9566 NotifyMotionArgs motionArgs =
9567 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9568 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009569 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009570 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009571 }
9572};
9573
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009574using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9575
9576TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9577 ScopedSilentDeath _silentDeath;
9578
Prabir Pradhand65552b2021-10-07 11:23:50 -07009579 auto [overlay, window] = setupStylusOverlayScenario();
9580 overlay->setTrustedOverlay(false);
9581 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9582 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9583 ".* not a trusted overlay");
9584}
9585
9586TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9587 auto [overlay, window] = setupStylusOverlayScenario();
9588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9589
9590 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9591 overlay->consumeMotionDown();
9592 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9593 overlay->consumeMotionUp();
9594
9595 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9596 window->consumeMotionDown();
9597 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9598 window->consumeMotionUp();
9599
9600 overlay->assertNoEvents();
9601 window->assertNoEvents();
9602}
9603
9604TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9605 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009606 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9608
9609 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9610 overlay->consumeMotionDown();
9611 window->consumeMotionDown();
9612 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9613 overlay->consumeMotionUp();
9614 window->consumeMotionUp();
9615
9616 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9617 window->consumeMotionDown();
9618 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9619 window->consumeMotionUp();
9620
9621 overlay->assertNoEvents();
9622 window->assertNoEvents();
9623}
9624
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009625/**
9626 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9627 * The scenario is as follows:
9628 * - The stylus interceptor overlay is configured as a spy window.
9629 * - The stylus interceptor spy receives the start of a new stylus gesture.
9630 * - It pilfers pointers and then configures itself to no longer be a spy.
9631 * - The stylus interceptor continues to receive the rest of the gesture.
9632 */
9633TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9634 auto [overlay, window] = setupStylusOverlayScenario();
9635 overlay->setSpy(true);
9636 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9637
9638 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9639 overlay->consumeMotionDown();
9640 window->consumeMotionDown();
9641
9642 // The interceptor pilfers the pointers.
9643 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9644 window->consumeMotionCancel();
9645
9646 // The interceptor configures itself so that it is no longer a spy.
9647 overlay->setSpy(false);
9648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9649
9650 // It continues to receive the rest of the stylus gesture.
9651 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9652 overlay->consumeMotionMove();
9653 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9654 overlay->consumeMotionUp();
9655
9656 window->assertNoEvents();
9657}
9658
Prabir Pradhan5735a322022-04-11 17:23:34 +00009659struct User {
9660 int32_t mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009661 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009662 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9663 std::unique_ptr<InputDispatcher>& mDispatcher;
9664
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009665 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009666 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9667
9668 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9669 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9670 ADISPLAY_ID_DEFAULT, {100, 200},
9671 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9672 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9673 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9674 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9675 }
9676
9677 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009678 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009679 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009680 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009681 mPolicyFlags);
9682 }
9683
9684 sp<FakeWindowHandle> createWindow() const {
9685 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9686 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009687 sp<FakeWindowHandle> window =
9688 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9689 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009690 window->setOwnerInfo(mPid, mUid);
9691 return window;
9692 }
9693};
9694
9695using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9696
9697TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009698 auto owner = User(mDispatcher, 10, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009699 auto window = owner.createWindow();
9700 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9701
9702 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9703 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9704 window->consumeMotionDown();
9705
9706 setFocusedWindow(window);
9707 window->consumeFocusEvent(true);
9708
9709 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9710 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9711 window->consumeKeyDown(ADISPLAY_ID_NONE);
9712}
9713
9714TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009715 auto owner = User(mDispatcher, 10, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009716 auto window = owner.createWindow();
9717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9718
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009719 auto rando = User(mDispatcher, 20, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009720 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9721 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9722
9723 setFocusedWindow(window);
9724 window->consumeFocusEvent(true);
9725
9726 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9727 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9728 window->assertNoEvents();
9729}
9730
9731TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009732 auto owner = User(mDispatcher, 10, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009733 auto window = owner.createWindow();
9734 auto spy = owner.createWindow();
9735 spy->setSpy(true);
9736 spy->setTrustedOverlay(true);
9737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9738
9739 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9740 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9741 spy->consumeMotionDown();
9742 window->consumeMotionDown();
9743}
9744
9745TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009746 auto owner = User(mDispatcher, 10, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009747 auto window = owner.createWindow();
9748
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009749 auto rando = User(mDispatcher, 20, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009750 auto randosSpy = rando.createWindow();
9751 randosSpy->setSpy(true);
9752 randosSpy->setTrustedOverlay(true);
9753 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9754
9755 // The event is targeted at owner's window, so injection should succeed, but the spy should
9756 // not receive the event.
9757 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9758 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9759 randosSpy->assertNoEvents();
9760 window->consumeMotionDown();
9761}
9762
9763TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009764 auto owner = User(mDispatcher, 10, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009765 auto window = owner.createWindow();
9766
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009767 auto rando = User(mDispatcher, 20, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009768 auto randosSpy = rando.createWindow();
9769 randosSpy->setSpy(true);
9770 randosSpy->setTrustedOverlay(true);
9771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9772
9773 // A user that has injection permission can inject into any window.
9774 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9775 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9776 ADISPLAY_ID_DEFAULT));
9777 randosSpy->consumeMotionDown();
9778 window->consumeMotionDown();
9779
9780 setFocusedWindow(randosSpy);
9781 randosSpy->consumeFocusEvent(true);
9782
9783 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9784 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9785 window->assertNoEvents();
9786}
9787
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009788TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009789 auto owner = User(mDispatcher, 10, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009790 auto window = owner.createWindow();
9791
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009792 auto rando = User(mDispatcher, 20, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009793 auto randosWindow = rando.createWindow();
9794 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9795 randosWindow->setWatchOutsideTouch(true);
9796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9797
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009798 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009799 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9800 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9801 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009802 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009803}
9804
Garfield Tane84e6f92019-08-29 17:28:41 -07009805} // namespace android::inputdispatcher