blob: 79f4d1ec642847c642df38ce295188662d43ac2b [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070019#include "TestInputListenerMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Cody Heiner166a5af2023-07-07 12:25:00 -070021#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070022#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080023#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080024#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070025#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070026#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000027#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080028#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080029#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080031#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080032#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100033
Garfield Tan1c7bc862020-01-28 13:24:04 -080034#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080035#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070036#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080037#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080038#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080039
Garfield Tan1c7bc862020-01-28 13:24:04 -080040using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050041using android::gui::FocusRequest;
42using android::gui::TouchOcclusionMode;
43using android::gui::WindowInfo;
44using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080045using android::os::InputEventInjectionResult;
46using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080047
Garfield Tane84e6f92019-08-29 17:28:41 -070048namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080049
Dominik Laskowski2f01d772022-03-23 16:01:29 -070050using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080051using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070052
Michael Wrightd02c5b62014-02-10 15:10:22 -080053// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000054static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
56// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000057static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080058static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080059
Jeff Brownf086ddb2014-02-11 14:28:48 -080060// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000061static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
62static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080063
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000064// Ensure common actions are interchangeable between keys and motions for convenience.
65static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
66static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080067static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
68static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
69static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
70static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070071static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080072static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080073static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080074static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075/**
76 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
77 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
78 * index 0) is the new pointer going down. The same pointer could have been placed at a different
79 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
80 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
81 * pointer id=0 leaves but the pointer id=1 remains.
82 */
83static constexpr int32_t POINTER_0_DOWN =
84 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080085static constexpr int32_t POINTER_1_DOWN =
86 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000087static constexpr int32_t POINTER_2_DOWN =
88 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000089static constexpr int32_t POINTER_3_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000091static constexpr int32_t POINTER_0_UP =
92 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080093static constexpr int32_t POINTER_1_UP =
94 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000095static constexpr int32_t POINTER_2_UP =
96 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080097
Antonio Kantek15beb512022-06-13 22:35:41 +000098// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000099static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000100static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000101
Antonio Kantek15beb512022-06-13 22:35:41 +0000102// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000103static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000104static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000105
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000106// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000107static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000108
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800109static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
110
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700111/**
112 * If we expect to receive the event, the timeout can be made very long. When the test are running
113 * correctly, we will actually never wait until the end of the timeout because the wait will end
114 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
115 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
116 * developer can see the failure quickly (on human scale).
117 */
118static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
119/**
120 * When no event is expected, we can have a very short timeout. A large value here would slow down
121 * the tests. In the unlikely event of system being too slow, the event may still be present but the
122 * timeout would complete before it is consumed. This would result in test flakiness. If this
123 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
124 * would get noticed and addressed quickly.
125 */
126static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
127
Arthur Hungc539dbb2022-12-08 07:45:36 +0000128static constexpr int expectedWallpaperFlags =
129 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
130
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800131using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
132
chaviwd1c23182019-12-20 18:44:56 -0800133struct PointF {
134 float x;
135 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800136 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800137};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800138
Gang Wang342c9272020-01-13 13:15:04 -0500139/**
140 * Return a DOWN key event with KEYCODE_A.
141 */
142static KeyEvent getTestKeyEvent() {
143 KeyEvent event;
144
Garfield Tanfbe732e2020-01-24 11:26:14 -0800145 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
146 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
147 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500148 return event;
149}
150
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000151static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
152 ASSERT_EQ(expectedAction, receivedAction)
153 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
154 << MotionEvent::actionToString(receivedAction);
155}
156
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800157MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
158 return arg.getDownTime() == downTime;
159}
160
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800161MATCHER_P(WithSource, source, "InputEvent with specified source") {
162 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
163 << inputEventSourceToString(arg.getSource());
164 return arg.getSource() == source;
165}
166
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800167MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
168 return arg.getFlags() == flags;
169}
170
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800171MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
172 if (arg.getPointerCount() != 1) {
173 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
174 return false;
175 }
Harry Cutts33476232023-01-30 19:57:29 +0000176 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800177}
178
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800179MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
180 return arg.getPointerCount() == pointerCount;
181}
182
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800183MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
184 // Build a map for the received pointers, by pointer id
185 std::map<int32_t /*pointerId*/, PointF> actualPointers;
186 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
187 const int32_t pointerId = arg.getPointerId(pointerIndex);
188 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
189 }
190 return pointers == actualPointers;
191}
192
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193// --- FakeInputDispatcherPolicy ---
194
195class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000196 struct AnrResult {
197 sp<IBinder> token{};
198 gui::Pid pid{gui::Pid::INVALID};
199 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800200
Michael Wrightd02c5b62014-02-10 15:10:22 -0800201public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000202 FakeInputDispatcherPolicy() = default;
203 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800204
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800205 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700206 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700207 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700208 EXPECT_EQ(event.getDisplayId(), args.displayId);
209
210 const auto& keyEvent = static_cast<const KeyEvent&>(event);
211 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
212 EXPECT_EQ(keyEvent.getAction(), args.action);
213 });
Jackal Guof9696682018-10-05 12:23:23 +0800214 }
215
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700216 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
217 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700218 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700219 EXPECT_EQ(event.getDisplayId(), args.displayId);
220
221 const auto& motionEvent = static_cast<const MotionEvent&>(event);
222 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
223 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000224 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
225 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
226 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
227 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 });
Jackal Guof9696682018-10-05 12:23:23 +0800229 }
230
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700231 void assertFilterInputEventWasNotCalled() {
232 std::scoped_lock lock(mLock);
233 ASSERT_EQ(nullptr, mFilteredEvent);
234 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800235
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800236 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700237 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800238 ASSERT_TRUE(mConfigurationChangedTime)
239 << "Timed out waiting for configuration changed call";
240 ASSERT_EQ(*mConfigurationChangedTime, when);
241 mConfigurationChangedTime = std::nullopt;
242 }
243
244 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700245 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800246 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800247 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
249 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
250 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
251 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
252 mLastNotifySwitch = std::nullopt;
253 }
254
chaviwfd6d3512019-03-25 13:23:49 -0700255 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700256 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800257 ASSERT_EQ(touchedToken, mOnPointerDownToken);
258 mOnPointerDownToken.clear();
259 }
260
261 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700262 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800263 ASSERT_TRUE(mOnPointerDownToken == nullptr)
264 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700265 }
266
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700267 // This function must be called soon after the expected ANR timer starts,
268 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500269 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700270 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500271 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800272 std::unique_lock lock(mLock);
273 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500274 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800275 ASSERT_NO_FATAL_FAILURE(
276 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500277 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700278 }
279
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000280 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 const sp<WindowInfoHandle>& window) {
282 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
283 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
284 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500285 }
286
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
288 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000289 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 std::unique_lock lock(mLock);
291 android::base::ScopedLockAssertion assumeLocked(mLock);
292 AnrResult result;
293 ASSERT_NO_FATAL_FAILURE(result =
294 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000295 ASSERT_EQ(expectedToken, result.token);
296 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500297 }
298
Prabir Pradhanedd96402022-02-15 01:46:16 -0800299 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000300 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500301 std::unique_lock lock(mLock);
302 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800303 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
304 const auto& [token, _] = result;
305 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000306 }
307
Prabir Pradhanedd96402022-02-15 01:46:16 -0800308 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000309 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800310 std::unique_lock lock(mLock);
311 android::base::ScopedLockAssertion assumeLocked(mLock);
312 AnrResult result;
313 ASSERT_NO_FATAL_FAILURE(
314 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000315 ASSERT_EQ(expectedToken, result.token);
316 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800317 }
318
319 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000320 sp<IBinder> getResponsiveWindowToken() {
321 std::unique_lock lock(mLock);
322 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800323 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
324 const auto& [token, _] = result;
325 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700326 }
327
328 void assertNotifyAnrWasNotCalled() {
329 std::scoped_lock lock(mLock);
330 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800331 ASSERT_TRUE(mAnrWindows.empty());
332 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500333 << "ANR was not called, but please also consume the 'connection is responsive' "
334 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700335 }
336
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000337 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800338 std::unique_lock lock(mLock);
339 base::ScopedLockAssertion assumeLocked(mLock);
340
341 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
342 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000343 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800344 enabled;
345 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000346 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
347 << ") to be called.";
348 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800349 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000350 auto request = *mPointerCaptureRequest;
351 mPointerCaptureRequest.reset();
352 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800353 }
354
355 void assertSetPointerCaptureNotCalled() {
356 std::unique_lock lock(mLock);
357 base::ScopedLockAssertion assumeLocked(mLock);
358
359 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000360 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800361 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000364 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800365 }
366
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700367 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
368 const sp<IBinder>& targetToken) {
369 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800370 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800371 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800372 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800373 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800374 }
375
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800376 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
377 std::unique_lock lock(mLock);
378 base::ScopedLockAssertion assumeLocked(mLock);
379 std::optional<sp<IBinder>> receivedToken =
380 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
381 mNotifyInputChannelBroken);
382 ASSERT_TRUE(receivedToken.has_value());
383 ASSERT_EQ(token, *receivedToken);
384 }
385
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800386 /**
387 * Set policy timeout. A value of zero means next key will not be intercepted.
388 */
389 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
390 mInterceptKeyTimeout = timeout;
391 }
392
Josep del Riob3981622023-04-18 15:49:45 +0000393 void assertUserActivityPoked() {
394 std::scoped_lock lock(mLock);
395 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
396 }
397
398 void assertUserActivityNotPoked() {
399 std::scoped_lock lock(mLock);
400 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
401 }
402
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000403 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000404 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
405 }
406
407 void assertNotifyDeviceInteractionWasNotCalled() {
408 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
409 }
410
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700412 std::mutex mLock;
413 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
414 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
415 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
416 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800417
Prabir Pradhan99987712020-11-10 18:43:05 -0800418 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000419
420 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800421
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700422 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700423 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800424 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
425 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700426 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800427 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
428 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700429
arthurhungf452d0b2021-01-06 00:19:52 +0800430 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800431 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000432 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800433
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800434 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
435
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000436 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000437
Prabir Pradhanedd96402022-02-15 01:46:16 -0800438 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
439 // for a specific container to become non-empty. When the container is non-empty, return the
440 // first entry from the container and erase it.
441 template <class T>
442 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
443 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
444 // If there is an ANR, Dispatcher won't be idle because there are still events
445 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
446 // before checking if ANR was called.
447 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
448 // to provide it some time to act. 100ms seems reasonable.
449 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
450 const std::chrono::time_point start = std::chrono::steady_clock::now();
451 std::optional<T> token =
452 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
453 if (!token.has_value()) {
454 ADD_FAILURE() << "Did not receive the ANR callback";
455 return {};
456 }
457
458 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
459 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
460 // the dispatcher started counting before this function was called
461 if (std::chrono::abs(timeout - waited) > 100ms) {
462 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
463 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
464 << "ms, but waited "
465 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
466 << "ms instead";
467 }
468 return *token;
469 }
470
471 template <class T>
472 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
473 std::queue<T>& storage,
474 std::unique_lock<std::mutex>& lock,
475 std::condition_variable& condition)
476 REQUIRES(mLock) {
477 condition.wait_for(lock, timeout,
478 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
479 if (storage.empty()) {
480 ADD_FAILURE() << "Did not receive the expected callback";
481 return std::nullopt;
482 }
483 T item = storage.front();
484 storage.pop();
485 return std::make_optional(item);
486 }
487
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600488 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700489 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800490 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800491 }
492
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000493 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700495 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800496 ASSERT_TRUE(pid.has_value());
497 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700498 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500499 }
500
Prabir Pradhanedd96402022-02-15 01:46:16 -0800501 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000502 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500503 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800504 ASSERT_TRUE(pid.has_value());
505 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500506 mNotifyAnr.notify_all();
507 }
508
509 void notifyNoFocusedWindowAnr(
510 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
511 std::scoped_lock lock(mLock);
512 mAnrApplications.push(applicationHandle);
513 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800514 }
515
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800516 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
517 std::scoped_lock lock(mLock);
518 mBrokenInputChannels.push(connectionToken);
519 mNotifyInputChannelBroken.notify_all();
520 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600522 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700523
Chris Yef59a2f42020-10-16 12:55:26 -0700524 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
525 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
526 const std::vector<float>& values) override {}
527
528 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
529 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000530
Chris Yefb552902021-02-03 17:18:37 -0800531 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
532
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700534 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000535 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700536 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000537 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
538 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800539 break;
540 }
541
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700542 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000543 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
544 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800545 break;
546 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700547 default: {
548 ADD_FAILURE() << "Should only filter keys or motions";
549 break;
550 }
Jackal Guof9696682018-10-05 12:23:23 +0800551 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552 return true;
553 }
554
Prabir Pradhana41d2442023-04-20 21:30:40 +0000555 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
556 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800557 // Clear intercept state when we handled the event.
558 mInterceptKeyTimeout = 0ms;
559 }
560 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800561
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600562 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563
Prabir Pradhana41d2442023-04-20 21:30:40 +0000564 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800565 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
566 // Clear intercept state so we could dispatch the event in next wake.
567 mInterceptKeyTimeout = 0ms;
568 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800569 }
570
Prabir Pradhana41d2442023-04-20 21:30:40 +0000571 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
572 uint32_t) override {
573 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574 }
575
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600576 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
577 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700578 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800579 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
580 * essentially a passthrough for notifySwitch.
581 */
Harry Cutts33476232023-01-30 19:57:29 +0000582 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583 }
584
Josep del Riob3981622023-04-18 15:49:45 +0000585 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
586 std::scoped_lock lock(mLock);
587 mPokedUserActivity = true;
588 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800589
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600590 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700591 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700592 mOnPointerDownToken = newToken;
593 }
594
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000595 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800596 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000597 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800598 mPointerCaptureChangedCondition.notify_all();
599 }
600
arthurhungf452d0b2021-01-06 00:19:52 +0800601 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
602 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800603 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800604 mDropTargetWindowToken = token;
605 }
606
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000607 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000608 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000609 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
610 }
611
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700612 void assertFilterInputEventWasCalledInternal(
613 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700614 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800615 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700616 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800617 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800618 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619};
620
Michael Wrightd02c5b62014-02-10 15:10:22 -0800621// --- InputDispatcherTest ---
622
623class InputDispatcherTest : public testing::Test {
624protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000625 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700626 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800627
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000628 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000629 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
630 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000632 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000636 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700637 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700641
642 /**
643 * Used for debugging when writing the test
644 */
645 void dumpDispatcherState() {
646 std::string dump;
647 mDispatcher->dump(dump);
648 std::stringstream ss(dump);
649 std::string to;
650
651 while (std::getline(ss, to, '\n')) {
652 ALOGE("%s", to.c_str());
653 }
654 }
Vishnu Nair958da932020-08-21 17:12:37 -0700655
Chavi Weingarten847e8512023-03-29 00:26:09 +0000656 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700657 FocusRequest request;
658 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000659 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700660 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
661 request.displayId = window->getInfo()->displayId;
662 mDispatcher->setFocusedWindow(request);
663 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664};
665
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
667 KeyEvent event;
668
669 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
671 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000672 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600673 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800674 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000675 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000676 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677 << "Should reject key events with undefined action.";
678
679 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000684 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000685 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686 << "Should reject key events with ACTION_MULTIPLE.";
687}
688
689TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
690 MotionEvent event;
691 PointerProperties pointerProperties[MAX_POINTERS + 1];
692 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800693 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 pointerProperties[i].clear();
695 pointerProperties[i].id = i;
696 pointerCoords[i].clear();
697 }
698
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800699 // Some constants commonly used below
700 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
701 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
702 constexpr int32_t metaState = AMETA_NONE;
703 constexpr MotionClassification classification = MotionClassification::NONE;
704
chaviw9eaa22c2020-07-01 16:21:27 -0700705 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000708 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000712 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with undefined action.";
717
718 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800720 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000724 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too large.";
729
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 AMOTION_EVENT_ACTION_POINTER_DOWN |
732 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700733 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000736 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too small.";
741
742 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800744 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
745 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
747 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000748 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too large.";
753
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700755 AMOTION_EVENT_ACTION_POINTER_UP |
756 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700757 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000760 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too small.";
765
766 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
768 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700769 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
771 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000772 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with 0 pointers.";
777
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000783 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with more than MAX_POINTERS pointers.";
788
789 // Rejects motion events with invalid pointer ids.
790 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids less than 0.";
801
802 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
813
814 // Rejects motion events with duplicate pointer ids.
815 pointerProperties[0].id = 1;
816 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with duplicate pointer ids.";
827}
828
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
830
831TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
832 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000833 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800834 ASSERT_TRUE(mDispatcher->waitForIdle());
835
836 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
837}
838
839TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000840 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
841 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000842 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800843
844 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
845 args.policyFlags |= POLICY_FLAG_TRUSTED;
846 mFakePolicy->assertNotifySwitchWasCalled(args);
847}
848
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700849namespace {
850
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700851static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700852// Default input dispatching timeout if there is no focused application or paused window
853// from which to determine an appropriate dispatching timeout.
854static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
855 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
856 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800857
858class FakeApplicationHandle : public InputApplicationHandle {
859public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700860 FakeApplicationHandle() {
861 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700862 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500863 mInfo.dispatchingTimeoutMillis =
864 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800866 virtual ~FakeApplicationHandle() {}
867
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000868 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700869
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500870 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
871 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700872 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800873};
874
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800875class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800876public:
Garfield Tan15601662020-09-22 15:32:38 -0700877 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800878 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700879 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800880 }
881
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700882 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700883 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700884 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 if (!consumeSeq) {
886 return nullptr;
887 }
888 finishEvent(*consumeSeq);
889 return event;
890 }
891
892 /**
893 * Receive an event without acknowledging it.
894 * Return the sequence number that could later be used to send finished signal.
895 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700896 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
897 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800898 uint32_t consumeSeq;
899 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800900
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800901 std::chrono::time_point start = std::chrono::steady_clock::now();
902 status_t status = WOULD_BLOCK;
903 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000904 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905 &event);
906 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700907 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800908 break;
909 }
910 }
911
912 if (status == WOULD_BLOCK) {
913 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915 }
916
917 if (status != OK) {
918 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700919 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 }
921 if (event == nullptr) {
922 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700923 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800924 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700925 if (outEvent != nullptr) {
926 *outEvent = event;
927 }
928 return consumeSeq;
929 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931 /**
932 * To be used together with "receiveEvent" to complete the consumption of an event.
933 */
934 void finishEvent(uint32_t consumeSeq) {
935 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
936 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
938
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000939 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
940 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
941 ASSERT_EQ(OK, status);
942 }
943
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700944 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 std::optional<int32_t> expectedDisplayId,
946 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700947 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800948
949 ASSERT_NE(nullptr, event) << mName.c_str()
950 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800951 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700952 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
953 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800954
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000955 if (expectedDisplayId.has_value()) {
956 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
957 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800958
Tiger Huang8664f8c2018-10-11 19:14:35 +0800959 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700960 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800961 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
962 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000963 if (expectedFlags.has_value()) {
964 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
965 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800966 break;
967 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700968 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800969 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000970 assertMotionAction(expectedAction, motionEvent.getAction());
971
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000972 if (expectedFlags.has_value()) {
973 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
974 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800975 break;
976 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100978 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
979 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800981 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
982 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700983 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000984 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
985 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700986 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800987 FAIL() << "Use 'consumeDragEvent' for DRAG events";
988 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800989 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800990 }
991
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800992 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700993 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800994
995 if (event == nullptr) {
996 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
997 return nullptr;
998 }
999
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 if (event->getType() != InputEventType::MOTION) {
1001 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001002 return nullptr;
1003 }
1004 return static_cast<MotionEvent*>(event);
1005 }
1006
1007 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1008 MotionEvent* motionEvent = consumeMotion();
1009 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1010 ASSERT_THAT(*motionEvent, matcher);
1011 }
1012
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001013 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001014 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001015 ASSERT_NE(nullptr, event) << mName.c_str()
1016 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001017 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1018 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001019
1020 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1021 << mName.c_str() << ": event displayId should always be NONE.";
1022
1023 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1024 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001025 }
1026
Prabir Pradhan99987712020-11-10 18:43:05 -08001027 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001028 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001029 ASSERT_NE(nullptr, event) << mName.c_str()
1030 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001031 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1032 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001033
1034 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1035 << mName.c_str() << ": event displayId should always be NONE.";
1036
1037 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1038 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1039 }
1040
arthurhungb89ccb02020-12-30 16:19:01 +08001041 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001042 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001043 ASSERT_NE(nullptr, event) << mName.c_str()
1044 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001045 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001046
1047 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
1050 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1051 EXPECT_EQ(isExiting, dragEvent.isExiting());
1052 EXPECT_EQ(x, dragEvent.getX());
1053 EXPECT_EQ(y, dragEvent.getY());
1054 }
1055
Antonio Kantekf16f2832021-09-28 04:39:20 +00001056 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001057 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001058 ASSERT_NE(nullptr, event) << mName.c_str()
1059 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001060 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1061 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001062
1063 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1064 << mName.c_str() << ": event displayId should always be NONE.";
1065 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1066 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1067 }
1068
chaviwd1c23182019-12-20 18:44:56 -08001069 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001070 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001071 if (event == nullptr) {
1072 return;
1073 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001074 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001075 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1076 ADD_FAILURE() << "Received key event "
1077 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001078 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001079 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1080 ADD_FAILURE() << "Received motion event "
1081 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001082 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001083 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1084 ADD_FAILURE() << "Received focus event, hasFocus = "
1085 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001086 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001087 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1088 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1089 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001090 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001091 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1092 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1093 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 }
1095 FAIL() << mName.c_str()
1096 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001097 }
1098
1099 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1100
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001101 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1102
chaviwd1c23182019-12-20 18:44:56 -08001103protected:
1104 std::unique_ptr<InputConsumer> mConsumer;
1105 PreallocatedInputEventFactory mEventFactory;
1106
1107 std::string mName;
1108};
1109
chaviw3277faf2021-05-19 16:45:23 -05001110class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001111public:
1112 static const int32_t WIDTH = 600;
1113 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001114
Chris Yea209fde2020-07-22 13:54:51 -07001115 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001116 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001117 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001118 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001119 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001120 base::Result<std::unique_ptr<InputChannel>> channel =
1121 dispatcher->createInputChannel(name);
1122 token = (*channel)->getConnectionToken();
1123 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001124 }
1125
1126 inputApplicationHandle->updateInfo();
1127 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1128
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001130 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001131 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001132 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001133 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001134 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001135 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001136 mInfo.globalScaleFactor = 1.0;
1137 mInfo.touchableRegion.clear();
1138 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001139 mInfo.ownerPid = WINDOW_PID;
1140 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001141 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001142 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001143 }
1144
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001145 sp<FakeWindowHandle> clone(int32_t displayId) {
1146 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1147 handle->mInfo = mInfo;
1148 handle->mInfo.displayId = displayId;
1149 handle->mInfo.id = sId++;
1150 handle->mInputReceiver = mInputReceiver;
1151 return handle;
1152 }
1153
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001154 void setTouchable(bool touchable) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1156 }
chaviwd1c23182019-12-20 18:44:56 -08001157
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001158 void setFocusable(bool focusable) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1160 }
1161
1162 void setVisible(bool visible) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1164 }
Vishnu Nair958da932020-08-21 17:12:37 -07001165
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001166 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001167 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001168 }
1169
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 void setPaused(bool paused) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1172 }
1173
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001174 void setPreventSplitting(bool preventSplitting) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001176 }
1177
1178 void setSlippery(bool slippery) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1180 }
1181
1182 void setWatchOutsideTouch(bool watchOutside) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1184 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001185
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001186 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1187
1188 void setInterceptsStylus(bool interceptsStylus) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1190 }
1191
1192 void setDropInput(bool dropInput) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1194 }
1195
1196 void setDropInputIfObscured(bool dropInputIfObscured) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1198 }
1199
1200 void setNoInputChannel(bool noInputChannel) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1202 }
1203
Josep del Riob3981622023-04-18 15:49:45 +00001204 void setDisableUserActivity(bool disableUserActivity) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1206 }
1207
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001208 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1209
chaviw3277faf2021-05-19 16:45:23 -05001210 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001211
Bernardo Rufino7393d172021-02-26 13:56:11 +00001212 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1213
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001214 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001215 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001216 mInfo.touchableRegion.clear();
1217 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001218
1219 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1220 ui::Transform translate;
1221 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1222 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001223 }
1224
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001225 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1226
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001227 void setIsWallpaper(bool isWallpaper) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1229 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001230
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001231 void setDupTouchToWallpaper(bool hasWallpaper) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1233 }
chaviwd1c23182019-12-20 18:44:56 -08001234
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001235 void setTrustedOverlay(bool trustedOverlay) {
1236 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1237 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001238
chaviw9eaa22c2020-07-01 16:21:27 -07001239 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1240 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1241 }
1242
1243 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001244
yunho.shinf4a80b82020-11-16 21:13:57 +09001245 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1246
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001247 KeyEvent* consumeKey() {
1248 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1249 if (event == nullptr) {
1250 ADD_FAILURE() << "Consume failed : no event";
1251 return nullptr;
1252 }
1253 if (event->getType() != InputEventType::KEY) {
1254 ADD_FAILURE() << "Instead of key event, got " << *event;
1255 return nullptr;
1256 }
1257 return static_cast<KeyEvent*>(event);
1258 }
1259
1260 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1261 KeyEvent* keyEvent = consumeKey();
1262 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1263 ASSERT_THAT(*keyEvent, matcher);
1264 }
1265
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001266 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001267 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001268 }
1269
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001270 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001271 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001272 }
1273
Svet Ganov5d3bc372020-01-26 23:11:07 -08001274 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001275 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001276 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1277 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001278 }
1279
1280 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001281 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001282 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1283 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001284 }
1285
1286 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001287 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001288 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1289 }
1290
1291 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1292 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001293 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001294 expectedFlags);
1295 }
1296
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1299 int32_t expectedFlags = 0) {
1300 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1301 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001302 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001303 }
1304
1305 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001306 int32_t expectedFlags = 0) {
1307 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1308 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001309 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001310 }
1311
1312 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001313 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001314 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001315 expectedFlags);
1316 }
1317
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001318 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1319 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001320 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001321 expectedFlags);
1322 }
1323
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001324 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1325 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001326 MotionEvent* motionEvent = consumeMotion();
1327 ASSERT_NE(nullptr, motionEvent);
1328 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1329 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1330 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001331 }
1332
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001333 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1334 ASSERT_NE(mInputReceiver, nullptr)
1335 << "Cannot consume events from a window with no receiver";
1336 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1337 }
1338
Prabir Pradhan99987712020-11-10 18:43:05 -08001339 void consumeCaptureEvent(bool hasCapture) {
1340 ASSERT_NE(mInputReceiver, nullptr)
1341 << "Cannot consume events from a window with no receiver";
1342 mInputReceiver->consumeCaptureEvent(hasCapture);
1343 }
1344
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001345 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1346 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001347 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001348 ASSERT_THAT(*motionEvent, matcher);
1349 }
1350
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001351 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001352 std::optional<int32_t> expectedDisplayId,
1353 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001354 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1355 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1356 expectedFlags);
1357 }
1358
arthurhungb89ccb02020-12-30 16:19:01 +08001359 void consumeDragEvent(bool isExiting, float x, float y) {
1360 mInputReceiver->consumeDragEvent(isExiting, x, y);
1361 }
1362
Antonio Kantekf16f2832021-09-28 04:39:20 +00001363 void consumeTouchModeEvent(bool inTouchMode) {
1364 ASSERT_NE(mInputReceiver, nullptr)
1365 << "Cannot consume events from a window with no receiver";
1366 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1367 }
1368
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001369 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001370 if (mInputReceiver == nullptr) {
1371 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1372 return std::nullopt;
1373 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001374 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001375 }
1376
1377 void finishEvent(uint32_t sequenceNum) {
1378 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1379 mInputReceiver->finishEvent(sequenceNum);
1380 }
1381
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001382 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1383 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1384 mInputReceiver->sendTimeline(inputEventId, timeline);
1385 }
1386
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001387 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001388 if (mInputReceiver == nullptr) {
1389 return nullptr;
1390 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001391 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001392 }
1393
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001394 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001395 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001396 if (event == nullptr) {
1397 ADD_FAILURE() << "Consume failed : no event";
1398 return nullptr;
1399 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001400 if (event->getType() != InputEventType::MOTION) {
1401 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001402 return nullptr;
1403 }
1404 return static_cast<MotionEvent*>(event);
1405 }
1406
Arthur Hungb92218b2018-08-14 12:00:21 +08001407 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001408 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001409 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001410 return; // Can't receive events if the window does not have input channel
1411 }
1412 ASSERT_NE(nullptr, mInputReceiver)
1413 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001414 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001415 }
1416
chaviwaf87b3e2019-10-01 16:59:28 -07001417 sp<IBinder> getToken() { return mInfo.token; }
1418
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001419 const std::string& getName() { return mName; }
1420
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001421 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001422 mInfo.ownerPid = ownerPid;
1423 mInfo.ownerUid = ownerUid;
1424 }
1425
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001426 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001427
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001428 void destroyReceiver() { mInputReceiver = nullptr; }
1429
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001430 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1431
chaviwd1c23182019-12-20 18:44:56 -08001432private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001433 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001434 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001435 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001436 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001437 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001438};
1439
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001440std::atomic<int32_t> FakeWindowHandle::sId{1};
1441
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001442static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001443 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001444 int32_t displayId = ADISPLAY_ID_NONE,
1445 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001446 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001447 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001448 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001449 KeyEvent event;
1450 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1451
1452 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001453 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001454 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1455 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001456
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001457 if (!allowKeyRepeat) {
1458 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1459 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001460 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001461 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001462}
1463
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001464static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1465 InputEventInjectionResult result =
1466 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1467 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1468 if (result != InputEventInjectionResult::TIMED_OUT) {
1469 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1470 }
1471}
1472
1473static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001474 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001475 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001476}
1477
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001478// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1479// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1480// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001481static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1482 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001483 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001484 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001485 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001486}
1487
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001488static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001489 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001490 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001491}
1492
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001493static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001494 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001495 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001496 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001497 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001498 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1499 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001500}
1501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001502static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001503 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1504 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001505 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001506 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1507 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001508 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001509 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001510 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001511 MotionEventBuilder motionBuilder =
1512 MotionEventBuilder(action, source)
1513 .displayId(displayId)
1514 .eventTime(eventTime)
1515 .rawXCursorPosition(cursorPosition.x)
1516 .rawYCursorPosition(cursorPosition.y)
1517 .pointer(
1518 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1519 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1520 motionBuilder.downTime(eventTime);
1521 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001522
1523 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001524 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1525 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001526}
1527
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001528static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1529 int32_t displayId,
1530 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001531 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001532}
1533
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001534static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1535 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001536 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001537 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001538}
1539
Jackal Guof9696682018-10-05 12:23:23 +08001540static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1541 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1542 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001543 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001544 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1545 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001546
1547 return args;
1548}
1549
Josep del Riob3981622023-04-18 15:49:45 +00001550static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1551 int32_t displayId = ADISPLAY_ID_NONE) {
1552 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1553 // Define a valid key event.
1554 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001555 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001556 currentTime);
1557
1558 return args;
1559}
1560
1561static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1562 int32_t displayId = ADISPLAY_ID_NONE) {
1563 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1564 // Define a valid key event.
1565 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001566 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001567 AMETA_NONE, currentTime);
1568
1569 return args;
1570}
1571
Prabir Pradhan678438e2023-04-13 19:32:51 +00001572[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1573 int32_t displayId,
1574 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001575 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001576 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1577 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1578 }
1579
chaviwd1c23182019-12-20 18:44:56 -08001580 PointerProperties pointerProperties[pointerCount];
1581 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001582
chaviwd1c23182019-12-20 18:44:56 -08001583 for (size_t i = 0; i < pointerCount; i++) {
1584 pointerProperties[i].clear();
1585 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001586 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001587
chaviwd1c23182019-12-20 18:44:56 -08001588 pointerCoords[i].clear();
1589 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1590 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1591 }
Jackal Guof9696682018-10-05 12:23:23 +08001592
1593 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1594 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001595 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001596 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1597 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001598 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001599 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001600 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001601 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001602
1603 return args;
1604}
1605
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001606static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1607 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1608}
1609
chaviwd1c23182019-12-20 18:44:56 -08001610static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1611 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1612}
1613
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001614static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1615 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001616 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001617}
1618
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001619} // namespace
1620
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001621/**
1622 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1623 * broken channel.
1624 */
1625TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1627 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001628 sp<FakeWindowHandle>::make(application, mDispatcher,
1629 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001630
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001631 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001632
1633 // Window closes its channel, but the window remains.
1634 window->destroyReceiver();
1635 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1636}
1637
Arthur Hungb92218b2018-08-14 12:00:21 +08001638TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001640 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1641 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001642
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001643 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001645 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001647
1648 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001649 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001650}
1651
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001652TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001654 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1655 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001656
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001657 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001658 // Inject a MotionEvent to an unknown display.
1659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001660 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1662
1663 // Window should receive motion event.
1664 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1665}
1666
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001667/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001668 * Calling onWindowInfosChanged once should not cause any issues.
1669 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001670 * called twice.
1671 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001672TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1675 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001676 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001678 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001680 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001681 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001683
1684 // Window should receive motion event.
1685 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1686}
1687
1688/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001689 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 */
1691TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001693 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1694 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001697 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1698 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703
1704 // Window should receive motion event.
1705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1706}
1707
Arthur Hungb92218b2018-08-14 12:00:21 +08001708// The foreground window should receive the first touch down event.
1709TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001711 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001712 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001713 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001714 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001715
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001716 mDispatcher->onWindowInfosChanged(
1717 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001719 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001721
1722 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001723 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001724 windowSecond->assertNoEvents();
1725}
1726
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001727/**
1728 * Two windows: A top window, and a wallpaper behind the window.
1729 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1730 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001731 * 1. foregroundWindow <-- dup touch to wallpaper
1732 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001733 */
1734TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1736 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001737 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001738 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001739 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001740 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001741 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001742
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001743 mDispatcher->onWindowInfosChanged(
1744 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001747 {100, 200}))
1748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1749
1750 // Both foreground window and its wallpaper should receive the touch down
1751 foregroundWindow->consumeMotionDown();
1752 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1753
1754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001755 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001756 ADISPLAY_ID_DEFAULT, {110, 200}))
1757 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1758
1759 foregroundWindow->consumeMotionMove();
1760 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1761
1762 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001763 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001764 foregroundWindow->consumeMotionCancel();
1765 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1766 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1767}
1768
1769/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001770 * Two fingers down on the window, and lift off the first finger.
1771 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1772 * contains a single pointer.
1773 */
1774TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1776 sp<FakeWindowHandle> window =
1777 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1778
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001779 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001780 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001781 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1782 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1783 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001784 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001785 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1786 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1787 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1788 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001789 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001790 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, 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 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1795 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1796 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1797
1798 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001799 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1801 window->consumeMotionEvent(
1802 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1803}
1804
1805/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001806 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1807 * with the following differences:
1808 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1809 * clean up the connection.
1810 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1811 * Ensure that there's no crash in the dispatcher.
1812 */
1813TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1815 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001816 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001817 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001818 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001819 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001820 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001821
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001822 mDispatcher->onWindowInfosChanged(
1823 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826 {100, 200}))
1827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1828
1829 // Both foreground window and its wallpaper should receive the touch down
1830 foregroundWindow->consumeMotionDown();
1831 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1832
1833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001834 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001835 ADISPLAY_ID_DEFAULT, {110, 200}))
1836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1837
1838 foregroundWindow->consumeMotionMove();
1839 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1840
1841 // Wallpaper closes its channel, but the window remains.
1842 wallpaperWindow->destroyReceiver();
1843 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1844
1845 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1846 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001847 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001848 foregroundWindow->consumeMotionCancel();
1849}
1850
Arthur Hungc539dbb2022-12-08 07:45:36 +00001851class ShouldSplitTouchFixture : public InputDispatcherTest,
1852 public ::testing::WithParamInterface<bool> {};
1853INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1854 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001855/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001856 * A single window that receives touch (on top), and a wallpaper window underneath it.
1857 * The top window gets a multitouch gesture.
1858 * Ensure that wallpaper gets the same gesture.
1859 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001860TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001862 sp<FakeWindowHandle> foregroundWindow =
1863 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1864 foregroundWindow->setDupTouchToWallpaper(true);
1865 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866
1867 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001868 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001869 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001871 mDispatcher->onWindowInfosChanged(
1872 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001873
1874 // Touch down on top window
1875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001876 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877 {100, 100}))
1878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1879
1880 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001881 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1883
1884 // Second finger down on the top window
1885 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001886 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001887 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001888 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1889 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 .build();
1891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001892 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 InputEventInjectionSync::WAIT_FOR_RESULT))
1894 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1895
Harry Cutts33476232023-01-30 19:57:29 +00001896 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1897 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001898 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001899
1900 const MotionEvent secondFingerUpEvent =
1901 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1902 .displayId(ADISPLAY_ID_DEFAULT)
1903 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001904 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1905 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001906 .build();
1907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001908 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001909 InputEventInjectionSync::WAIT_FOR_RESULT))
1910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1911 foregroundWindow->consumeMotionPointerUp(0);
1912 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1913
1914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001915 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001916 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1917 AINPUT_SOURCE_TOUCHSCREEN)
1918 .displayId(ADISPLAY_ID_DEFAULT)
1919 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001920 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001921 .x(100)
1922 .y(100))
1923 .build(),
1924 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1926 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1927 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001928}
1929
1930/**
1931 * Two windows: a window on the left and window on the right.
1932 * A third window, wallpaper, is behind both windows, and spans both top windows.
1933 * The first touch down goes to the left window. A second pointer touches down on the right window.
1934 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1935 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1936 * ACTION_POINTER_DOWN(1).
1937 */
1938TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1940 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001941 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001942 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001943 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001944
1945 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001946 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001948 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001949
1950 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001951 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001953 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001954
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001955 mDispatcher->onWindowInfosChanged(
1956 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1957 {},
1958 0,
1959 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960
1961 // Touch down on left window
1962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001963 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964 {100, 100}))
1965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1966
1967 // Both foreground window and its wallpaper should receive the touch down
1968 leftWindow->consumeMotionDown();
1969 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1970
1971 // Second finger down on the right window
1972 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001973 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001975 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1976 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977 .build();
1978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001979 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980 InputEventInjectionSync::WAIT_FOR_RESULT))
1981 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1982
1983 leftWindow->consumeMotionMove();
1984 // Since the touch is split, right window gets ACTION_DOWN
1985 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001986 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987 expectedWallpaperFlags);
1988
1989 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001990 mDispatcher->onWindowInfosChanged(
1991 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001992 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,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002005 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002006 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
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002035 mDispatcher->onWindowInfosChanged(
2036 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2037 {},
2038 0,
2039 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002040
Arthur Hungc539dbb2022-12-08 07:45:36 +00002041 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002043 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002044 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002045 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002046
2047 // Both foreground window and its wallpaper should receive the touch down
2048 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002049 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2050
Arthur Hungc539dbb2022-12-08 07:45:36 +00002051 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002053 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002054 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2056
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057 leftWindow->consumeMotionCancel();
2058 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2059 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002060}
2061
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002062/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002063 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2064 * interactive, it might stop sending this flag.
2065 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2066 * to have a consistent input stream.
2067 *
2068 * Test procedure:
2069 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2070 * DOWN (new gesture).
2071 *
2072 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2073 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2074 *
2075 * We technically just need a single window here, but we are using two windows (spy on top and a
2076 * regular window below) to emulate the actual situation where it happens on the device.
2077 */
2078TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2080 sp<FakeWindowHandle> spyWindow =
2081 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2082 spyWindow->setFrame(Rect(0, 0, 200, 200));
2083 spyWindow->setTrustedOverlay(true);
2084 spyWindow->setSpy(true);
2085
2086 sp<FakeWindowHandle> window =
2087 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2088 window->setFrame(Rect(0, 0, 200, 200));
2089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002090 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002091 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002092
2093 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002094 mDispatcher->notifyMotion(
2095 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2096 .deviceId(touchDeviceId)
2097 .policyFlags(DEFAULT_POLICY_FLAGS)
2098 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2099 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002100
Prabir Pradhan678438e2023-04-13 19:32:51 +00002101 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2102 .deviceId(touchDeviceId)
2103 .policyFlags(DEFAULT_POLICY_FLAGS)
2104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2105 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2106 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002107 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2108 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2109 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2110 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2111
2112 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002113 mDispatcher->notifyMotion(
2114 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2115 .deviceId(touchDeviceId)
2116 .policyFlags(0)
2117 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2118 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2119 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002120 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2121 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2122
2123 // We don't need to reset the device to reproduce the issue, but the reset event typically
2124 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002125 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126
2127 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002128 mDispatcher->notifyMotion(
2129 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2130 .deviceId(touchDeviceId)
2131 .policyFlags(DEFAULT_POLICY_FLAGS)
2132 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2133 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2135 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2136
2137 // No more events
2138 spyWindow->assertNoEvents();
2139 window->assertNoEvents();
2140}
2141
2142/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002143 * Two windows: a window on the left and a window on the right.
2144 * Mouse is hovered from the right window into the left window.
2145 * Next, we tap on the left window, where the cursor was last seen.
2146 * The second tap is done onto the right window.
2147 * The mouse and tap are from two different devices.
2148 * We technically don't need to set the downtime / eventtime for these events, but setting these
2149 * explicitly helps during debugging.
2150 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2151 * In the buggy implementation, a tap on the right window would cause a crash.
2152 */
2153TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2155 sp<FakeWindowHandle> leftWindow =
2156 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2157 leftWindow->setFrame(Rect(0, 0, 200, 200));
2158
2159 sp<FakeWindowHandle> rightWindow =
2160 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2161 rightWindow->setFrame(Rect(200, 0, 400, 200));
2162
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002163 mDispatcher->onWindowInfosChanged(
2164 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002165 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2166 // stale.
2167 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2168 const int32_t mouseDeviceId = 6;
2169 const int32_t touchDeviceId = 4;
2170 // Move the cursor from right
2171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002172 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002173 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2174 AINPUT_SOURCE_MOUSE)
2175 .deviceId(mouseDeviceId)
2176 .downTime(baseTime + 10)
2177 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002178 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002179 .build()));
2180 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2181
2182 // .. to the left window
2183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002184 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2186 AINPUT_SOURCE_MOUSE)
2187 .deviceId(mouseDeviceId)
2188 .downTime(baseTime + 10)
2189 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002190 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002191 .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,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002196 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002197 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2198 AINPUT_SOURCE_TOUCHSCREEN)
2199 .deviceId(touchDeviceId)
2200 .downTime(baseTime + 40)
2201 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002202 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002203 .build()));
2204 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2205 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2206
2207 // release tap
2208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002209 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002210 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2211 AINPUT_SOURCE_TOUCHSCREEN)
2212 .deviceId(touchDeviceId)
2213 .downTime(baseTime + 40)
2214 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002215 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002216 .build()));
2217 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2218
2219 // Tap the window on the right
2220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002221 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002222 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2223 AINPUT_SOURCE_TOUCHSCREEN)
2224 .deviceId(touchDeviceId)
2225 .downTime(baseTime + 60)
2226 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002227 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002228 .build()));
2229 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2230
2231 // release tap
2232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002233 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002234 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2235 AINPUT_SOURCE_TOUCHSCREEN)
2236 .deviceId(touchDeviceId)
2237 .downTime(baseTime + 60)
2238 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002239 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 .build()));
2241 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2242
2243 // No more events
2244 leftWindow->assertNoEvents();
2245 rightWindow->assertNoEvents();
2246}
2247
2248/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002249 * Start hovering in a window. While this hover is still active, make another window appear on top.
2250 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2251 * While the top window is present, the hovering is stopped.
2252 * Later, hovering gets resumed again.
2253 * Ensure that new hover gesture is handled correctly.
2254 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2255 * to the window that's currently being hovered over.
2256 */
2257TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2259 sp<FakeWindowHandle> window =
2260 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2261 window->setFrame(Rect(0, 0, 200, 200));
2262
2263 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002264 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002265
2266 // Start hovering in the window
2267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2268 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2269 .build());
2270 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2271
2272 // Now, an obscuring window appears!
2273 sp<FakeWindowHandle> obscuringWindow =
2274 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2275 ADISPLAY_ID_DEFAULT,
2276 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2277 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2278 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2279 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2280 obscuringWindow->setNoInputChannel(true);
2281 obscuringWindow->setFocusable(false);
2282 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002283 mDispatcher->onWindowInfosChanged(
2284 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002285
2286 // While this new obscuring window is present, the hovering is stopped
2287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2288 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2289 .build());
2290 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2291
2292 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002293 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002294
2295 // And a new hover gesture starts.
2296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2297 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2298 .build());
2299 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2300}
2301
2302/**
2303 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2304 * the obscuring window.
2305 */
2306TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2308 sp<FakeWindowHandle> window =
2309 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2310 window->setFrame(Rect(0, 0, 200, 200));
2311
2312 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002313 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002314
2315 // Start hovering in the window
2316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2317 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2318 .build());
2319 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2320
2321 // Now, an obscuring window appears!
2322 sp<FakeWindowHandle> obscuringWindow =
2323 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2324 ADISPLAY_ID_DEFAULT,
2325 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2326 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2327 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2328 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2329 obscuringWindow->setNoInputChannel(true);
2330 obscuringWindow->setFocusable(false);
2331 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002332 mDispatcher->onWindowInfosChanged(
2333 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002334
2335 // While this new obscuring window is present, the hovering continues. The event can't go to the
2336 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2337 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2338 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2339 .build());
2340 obscuringWindow->assertNoEvents();
2341 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2342
2343 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002344 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002345
2346 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2347 // so it should generate a HOVER_ENTER
2348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2349 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2350 .build());
2351 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2352
2353 // Now the MOVE should be getting dispatched normally
2354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2355 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2356 .build());
2357 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2358}
2359
2360/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002361 * Two windows: a window on the left and a window on the right.
2362 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2363 * down. Then, on the left window, also place second touch pointer down.
2364 * This test tries to reproduce a crash.
2365 * In the buggy implementation, second pointer down on the left window would cause a crash.
2366 */
2367TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2369 sp<FakeWindowHandle> leftWindow =
2370 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2371 leftWindow->setFrame(Rect(0, 0, 200, 200));
2372
2373 sp<FakeWindowHandle> rightWindow =
2374 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2375 rightWindow->setFrame(Rect(200, 0, 400, 200));
2376
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002377 mDispatcher->onWindowInfosChanged(
2378 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002379
2380 const int32_t touchDeviceId = 4;
2381 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002382
2383 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002384 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2385 .deviceId(mouseDeviceId)
2386 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2387 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002388 leftWindow->consumeMotionEvent(
2389 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2390
2391 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2393 .deviceId(mouseDeviceId)
2394 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2395 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2396 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002397
2398 leftWindow->consumeMotionEvent(
2399 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2400 leftWindow->consumeMotionEvent(
2401 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2402
Prabir Pradhan678438e2023-04-13 19:32:51 +00002403 mDispatcher->notifyMotion(
2404 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2405 .deviceId(mouseDeviceId)
2406 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2407 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2408 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2409 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002410 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2411
2412 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2414 .deviceId(touchDeviceId)
2415 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2416 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002417 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2418
2419 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2420
2421 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002422 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2423 .deviceId(touchDeviceId)
2424 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2425 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2426 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002427 leftWindow->consumeMotionEvent(
2428 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2429 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2430 // current implementation.
2431 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2432 rightWindow->consumeMotionEvent(
2433 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2434
2435 leftWindow->assertNoEvents();
2436 rightWindow->assertNoEvents();
2437}
2438
2439/**
2440 * On a single window, use two different devices: mouse and touch.
2441 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2442 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2443 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2444 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2445 * represent a new gesture.
2446 */
2447TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2449 sp<FakeWindowHandle> window =
2450 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2451 window->setFrame(Rect(0, 0, 400, 400));
2452
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002453 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002454
2455 const int32_t touchDeviceId = 4;
2456 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002457
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002458 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2460 .deviceId(touchDeviceId)
2461 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2462 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002463 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002464 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2465 .deviceId(touchDeviceId)
2466 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2467 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2468 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002469 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002470 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2471 .deviceId(touchDeviceId)
2472 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2473 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2474 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002475 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2476 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2477 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2478
2479 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2481 .deviceId(mouseDeviceId)
2482 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2483 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2484 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002485
2486 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002487 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002488 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2489
Prabir Pradhan678438e2023-04-13 19:32:51 +00002490 mDispatcher->notifyMotion(
2491 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2492 .deviceId(mouseDeviceId)
2493 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2494 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2495 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2496 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002497 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2498
2499 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002500 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2501 .deviceId(touchDeviceId)
2502 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2503 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2504 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002505 // The pointer_down event should be ignored
2506 window->assertNoEvents();
2507}
2508
2509/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002510 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2511 * the injected event.
2512 */
2513TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2515 sp<FakeWindowHandle> window =
2516 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2517 window->setFrame(Rect(0, 0, 400, 400));
2518
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002520
2521 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002522 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2523 // completion.
2524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002525 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002526 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2527 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002528 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002529 .build()));
2530 window->consumeMotionEvent(
2531 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2532
2533 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2534 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2536 .deviceId(touchDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2538 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002539
2540 window->consumeMotionEvent(
2541 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2542 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2543}
2544
2545/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002546 * This test is similar to the test above, but the sequence of injected events is different.
2547 *
2548 * Two windows: a window on the left and a window on the right.
2549 * Mouse is hovered over the left window.
2550 * Next, we tap on the left window, where the cursor was last seen.
2551 *
2552 * After that, we inject one finger down onto the right window, and then a second finger down onto
2553 * the left window.
2554 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2555 * window (first), and then another on the left window (second).
2556 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2557 * In the buggy implementation, second finger down on the left window would cause a crash.
2558 */
2559TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2561 sp<FakeWindowHandle> leftWindow =
2562 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2563 leftWindow->setFrame(Rect(0, 0, 200, 200));
2564
2565 sp<FakeWindowHandle> rightWindow =
2566 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2567 rightWindow->setFrame(Rect(200, 0, 400, 200));
2568
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002569 mDispatcher->onWindowInfosChanged(
2570 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002571
2572 const int32_t mouseDeviceId = 6;
2573 const int32_t touchDeviceId = 4;
2574 // Hover over the left window. Keep the cursor there.
2575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002576 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002577 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2578 AINPUT_SOURCE_MOUSE)
2579 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002580 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002581 .build()));
2582 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2583
2584 // Tap on left window
2585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002586 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002587 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2588 AINPUT_SOURCE_TOUCHSCREEN)
2589 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002590 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002591 .build()));
2592
2593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002594 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002595 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2596 AINPUT_SOURCE_TOUCHSCREEN)
2597 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002598 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002599 .build()));
2600 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2601 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2602 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2603
2604 // First finger down on right window
2605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002606 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002607 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2608 AINPUT_SOURCE_TOUCHSCREEN)
2609 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002610 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002611 .build()));
2612 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2613
2614 // Second finger down on the left window
2615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002616 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002617 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2618 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002619 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2620 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002621 .build()));
2622 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2623 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2624
2625 // No more events
2626 leftWindow->assertNoEvents();
2627 rightWindow->assertNoEvents();
2628}
2629
2630/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002631 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2632 * While the touch is down, new hover events from the stylus device should be ignored. After the
2633 * touch is gone, stylus hovering should start working again.
2634 */
2635TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2637 sp<FakeWindowHandle> window =
2638 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2639 window->setFrame(Rect(0, 0, 200, 200));
2640
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002641 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002642
2643 const int32_t stylusDeviceId = 5;
2644 const int32_t touchDeviceId = 4;
2645 // Start hovering with stylus
2646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002647 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002648 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2649 AINPUT_SOURCE_STYLUS)
2650 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002651 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002652 .build()));
2653 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2654
2655 // Finger down on the window
2656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002657 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002658 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2659 AINPUT_SOURCE_TOUCHSCREEN)
2660 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002661 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002662 .build()));
2663 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2664 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2665
2666 // Try to continue hovering with stylus. Since we are already down, injection should fail
2667 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002668 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002669 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2670 AINPUT_SOURCE_STYLUS)
2671 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002672 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002673 .build()));
2674 // No event should be sent. This event should be ignored because a pointer from another device
2675 // is already down.
2676
2677 // Lift up the finger
2678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002679 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002680 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2681 AINPUT_SOURCE_TOUCHSCREEN)
2682 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002683 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002684 .build()));
2685 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2686
2687 // Now that the touch is gone, stylus hovering should start working again
2688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002689 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002690 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2691 AINPUT_SOURCE_STYLUS)
2692 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002693 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002694 .build()));
2695 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2696 // No more events
2697 window->assertNoEvents();
2698}
2699
2700/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002701 * A spy window above a window with no input channel.
2702 * Start hovering with a stylus device, and then tap with it.
2703 * Ensure spy window receives the entire sequence.
2704 */
2705TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2707 sp<FakeWindowHandle> spyWindow =
2708 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2709 spyWindow->setFrame(Rect(0, 0, 200, 200));
2710 spyWindow->setTrustedOverlay(true);
2711 spyWindow->setSpy(true);
2712 sp<FakeWindowHandle> window =
2713 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2714 window->setNoInputChannel(true);
2715 window->setFrame(Rect(0, 0, 200, 200));
2716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002717 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002718
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002719 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2721 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2722 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002723 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2724 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2726 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2727 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002728 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2729
2730 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2732 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2733 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002734 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2735
2736 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2739 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002740 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2741
2742 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2744 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2745 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002746 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2747 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2749 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2750 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002751 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2752
2753 // No more events
2754 spyWindow->assertNoEvents();
2755 window->assertNoEvents();
2756}
2757
2758/**
2759 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2760 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2761 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2762 * While the mouse is down, new move events from the touch device should be ignored.
2763 */
2764TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2766 sp<FakeWindowHandle> spyWindow =
2767 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2768 spyWindow->setFrame(Rect(0, 0, 200, 200));
2769 spyWindow->setTrustedOverlay(true);
2770 spyWindow->setSpy(true);
2771 sp<FakeWindowHandle> window =
2772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2773 window->setFrame(Rect(0, 0, 200, 200));
2774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002775 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002776
2777 const int32_t mouseDeviceId = 7;
2778 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002779
2780 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002781 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2782 .deviceId(mouseDeviceId)
2783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2784 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002785 spyWindow->consumeMotionEvent(
2786 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2787 window->consumeMotionEvent(
2788 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2789
2790 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002791 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2792 .deviceId(touchDeviceId)
2793 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2794 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002795 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2796 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2797 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2798 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2799
Prabir Pradhan678438e2023-04-13 19:32:51 +00002800 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2801 .deviceId(touchDeviceId)
2802 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2803 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002804 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2805 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2806
2807 // Pilfer the stream
2808 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2809 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2810
Prabir Pradhan678438e2023-04-13 19:32:51 +00002811 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2812 .deviceId(touchDeviceId)
2813 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2814 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2816
2817 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2819 .deviceId(mouseDeviceId)
2820 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2821 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2822 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002823
2824 spyWindow->consumeMotionEvent(
2825 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2826 spyWindow->consumeMotionEvent(
2827 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2828 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2829
Prabir Pradhan678438e2023-04-13 19:32:51 +00002830 mDispatcher->notifyMotion(
2831 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2832 .deviceId(mouseDeviceId)
2833 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2834 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2835 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2836 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002837 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2838 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2839
2840 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002841 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2842 .deviceId(mouseDeviceId)
2843 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2844 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2845 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002846 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2847 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2848
2849 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2851 .deviceId(touchDeviceId)
2852 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2853 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002854
2855 // No more events
2856 spyWindow->assertNoEvents();
2857 window->assertNoEvents();
2858}
2859
2860/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002861 * On the display, have a single window, and also an area where there's no window.
2862 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2863 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2864 */
2865TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2867 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002868 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002869
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002870 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002871
2872 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002873 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002874
2875 mDispatcher->waitForIdle();
2876 window->assertNoEvents();
2877
2878 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002879 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002880 mDispatcher->waitForIdle();
2881 window->consumeMotionDown();
2882}
2883
2884/**
2885 * Same test as above, but instead of touching the empty space, the first touch goes to
2886 * non-touchable window.
2887 */
2888TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2890 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002891 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002892 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2893 window1->setTouchable(false);
2894 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002895 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002896 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002898 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002899
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002900 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002901 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002902
2903 mDispatcher->waitForIdle();
2904 window1->assertNoEvents();
2905 window2->assertNoEvents();
2906
2907 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002908 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002909 mDispatcher->waitForIdle();
2910 window2->consumeMotionDown();
2911}
2912
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002913/**
2914 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2915 * to the event time of the first ACTION_DOWN sent to the particular window.
2916 */
2917TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2919 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002920 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002921 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2922 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002923 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002924 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2925
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002926 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002927
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002928 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002929 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002930
2931 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002932
2933 MotionEvent* motionEvent1 = window1->consumeMotion();
2934 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002935 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002936 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
2937 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002938
2939 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002940 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002941 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002942 MotionEvent* motionEvent2 = window2->consumeMotion();
2943 ASSERT_NE(motionEvent2, nullptr);
2944 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002945 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002946 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002947
2948 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002949 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002950 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002951 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002952
2953 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002954 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002955 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002956 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002957
2958 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2959 window1->consumeMotionMove();
2960 window1->assertNoEvents();
2961
2962 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002963 mDispatcher->notifyMotion(
2964 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002966 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002967
Prabir Pradhan678438e2023-04-13 19:32:51 +00002968 mDispatcher->notifyMotion(
2969 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002970 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002971 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002972}
2973
Garfield Tandf26e862020-07-01 20:18:19 -07002974TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002975 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002976 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002977 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002978 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002979 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002980 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002981 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002982
2983 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2984
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002985 mDispatcher->onWindowInfosChanged(
2986 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07002987
2988 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002990 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07002991 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2992 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002993 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07002994 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002995 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002996
2997 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002999 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003000 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3001 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003003 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003004 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3005 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003006
3007 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003009 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003010 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3011 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003012 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003013 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003014 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3015 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003016
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003018 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003019 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3020 AINPUT_SOURCE_MOUSE)
3021 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3022 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003024 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003025 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003026
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003028 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003029 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3030 AINPUT_SOURCE_MOUSE)
3031 .buttonState(0)
3032 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
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 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003036
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003038 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003039 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3040 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003041 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003042 .build()));
3043 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3044
3045 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003047 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003048 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3049 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003050 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003051 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003052 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003053
3054 // No more events
3055 windowLeft->assertNoEvents();
3056 windowRight->assertNoEvents();
3057}
3058
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003059/**
3060 * Put two fingers down (and don't release them) and click the mouse button.
3061 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3062 * currently active gesture should be canceled, and the new one should proceed.
3063 */
3064TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3065 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3066 sp<FakeWindowHandle> window =
3067 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3068 window->setFrame(Rect(0, 0, 600, 800));
3069
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003070 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003071
3072 const int32_t touchDeviceId = 4;
3073 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003074
3075 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3077 .deviceId(touchDeviceId)
3078 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3079 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003080
Prabir Pradhan678438e2023-04-13 19:32:51 +00003081 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3082 .deviceId(touchDeviceId)
3083 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3084 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3085 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003086 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3087 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3088
3089 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003090 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3091 .deviceId(mouseDeviceId)
3092 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3093 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3094 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003095 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3096 WithPointerCount(2u)));
3097 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3098
Prabir Pradhan678438e2023-04-13 19:32:51 +00003099 mDispatcher->notifyMotion(
3100 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3101 .deviceId(mouseDeviceId)
3102 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3103 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3104 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3107
3108 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3109 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003110 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3111 .deviceId(touchDeviceId)
3112 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3113 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3114 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115 window->assertNoEvents();
3116}
3117
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003118TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3120
3121 sp<FakeWindowHandle> spyWindow =
3122 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3123 spyWindow->setFrame(Rect(0, 0, 600, 800));
3124 spyWindow->setTrustedOverlay(true);
3125 spyWindow->setSpy(true);
3126 sp<FakeWindowHandle> window =
3127 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3128 window->setFrame(Rect(0, 0, 600, 800));
3129
3130 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003131 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003132
3133 // Send mouse cursor to the window
3134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003135 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003136 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3137 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003139 .build()));
3140
3141 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3142 WithSource(AINPUT_SOURCE_MOUSE)));
3143 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3144 WithSource(AINPUT_SOURCE_MOUSE)));
3145
3146 window->assertNoEvents();
3147 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003148}
3149
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003150TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3152
3153 sp<FakeWindowHandle> spyWindow =
3154 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3155 spyWindow->setFrame(Rect(0, 0, 600, 800));
3156 spyWindow->setTrustedOverlay(true);
3157 spyWindow->setSpy(true);
3158 sp<FakeWindowHandle> window =
3159 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3160 window->setFrame(Rect(0, 0, 600, 800));
3161
3162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003163 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003164
3165 // Send mouse cursor to the window
3166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003167 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003168 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3169 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003170 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003171 .build()));
3172
3173 // Move mouse cursor
3174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003175 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003176 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3177 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003178 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003179 .build()));
3180
3181 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3182 WithSource(AINPUT_SOURCE_MOUSE)));
3183 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3184 WithSource(AINPUT_SOURCE_MOUSE)));
3185 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3186 WithSource(AINPUT_SOURCE_MOUSE)));
3187 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3188 WithSource(AINPUT_SOURCE_MOUSE)));
3189 // Touch down on the window
3190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003191 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003192 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3193 AINPUT_SOURCE_TOUCHSCREEN)
3194 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003195 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003196 .build()));
3197 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3198 WithSource(AINPUT_SOURCE_MOUSE)));
3199 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3200 WithSource(AINPUT_SOURCE_MOUSE)));
3201 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3202 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3203 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3204 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3205
3206 // pilfer the motion, retaining the gesture on the spy window.
3207 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3208 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3209 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3210
3211 // Touch UP on the window
3212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003213 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003214 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3215 AINPUT_SOURCE_TOUCHSCREEN)
3216 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003217 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003218 .build()));
3219 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3220 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3221
3222 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3223 // to send a new gesture. It should again go to both windows (spy and the window below), just
3224 // like the first gesture did, before pilfering. The window configuration has not changed.
3225
3226 // One more tap - DOWN
3227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003228 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003229 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3230 AINPUT_SOURCE_TOUCHSCREEN)
3231 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003232 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003233 .build()));
3234 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3235 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3236 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3237 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3238
3239 // Touch UP on the window
3240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003241 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003242 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3243 AINPUT_SOURCE_TOUCHSCREEN)
3244 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003245 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003246 .build()));
3247 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3248 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3249 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3250 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3251
3252 window->assertNoEvents();
3253 spyWindow->assertNoEvents();
3254}
3255
Garfield Tandf26e862020-07-01 20:18:19 -07003256// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3257// directly in this test.
3258TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003259 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003260 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003261 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003262 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003263
3264 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3265
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003266 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003267
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003269 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003270 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3271 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003272 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003273 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003274 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003275 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003277 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003278 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3279 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003280 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003281 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003282 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3283 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003284
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003286 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003287 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3288 AINPUT_SOURCE_MOUSE)
3289 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3290 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003291 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003292 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003293 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003294
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003296 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003297 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3298 AINPUT_SOURCE_MOUSE)
3299 .buttonState(0)
3300 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003301 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003302 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003303 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003304
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003306 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003307 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3308 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003309 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003310 .build()));
3311 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3312
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003313 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3314 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3315 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003316 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003317 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3318 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003320 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003321 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003322}
3323
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003324/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003325 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3326 * is generated.
3327 */
3328TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3330 sp<FakeWindowHandle> window =
3331 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3332 window->setFrame(Rect(0, 0, 1200, 800));
3333
3334 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3335
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003336 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003337
3338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3341 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003342 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003343 .build()));
3344 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3345
3346 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003347 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003348 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3349}
3350
3351/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003352 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3353 */
3354TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3355 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3356 sp<FakeWindowHandle> window =
3357 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3358 window->setFrame(Rect(0, 0, 1200, 800));
3359
3360 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3361
3362 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3363
3364 MotionEventBuilder hoverEnterBuilder =
3365 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3366 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3367 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3369 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3371 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3372 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3373 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3374}
3375
3376/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003377 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3378 */
3379TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3381 sp<FakeWindowHandle> window =
3382 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3383 window->setFrame(Rect(0, 0, 100, 100));
3384
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003385 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003386
3387 const int32_t mouseDeviceId = 7;
3388 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003389
3390 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3392 .deviceId(mouseDeviceId)
3393 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3394 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003395 window->consumeMotionEvent(
3396 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3397
3398 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3400 .deviceId(touchDeviceId)
3401 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3402 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003403
3404 window->consumeMotionEvent(
3405 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3406 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3407}
3408
3409/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003410 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003411 * The tap causes a HOVER_EXIT event to be generated because the current event
3412 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003413 */
3414TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3416 sp<FakeWindowHandle> window =
3417 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3418 window->setFrame(Rect(0, 0, 100, 100));
3419
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003420 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003421
3422 // Inject a hover_move from mouse.
3423 NotifyMotionArgs motionArgs =
3424 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3425 ADISPLAY_ID_DEFAULT, {{50, 50}});
3426 motionArgs.xCursorPosition = 50;
3427 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003428 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003429 ASSERT_NO_FATAL_FAILURE(
3430 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3431 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003432
3433 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003434 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3435 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3436 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003437 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003438 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3439 WithSource(AINPUT_SOURCE_MOUSE))));
3440
3441 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003442 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3443 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3444
Prabir Pradhan678438e2023-04-13 19:32:51 +00003445 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3446 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003447 ASSERT_NO_FATAL_FAILURE(
3448 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3449 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3450}
3451
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003452TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3454 sp<FakeWindowHandle> windowDefaultDisplay =
3455 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3456 ADISPLAY_ID_DEFAULT);
3457 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3458 sp<FakeWindowHandle> windowSecondDisplay =
3459 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3460 SECOND_DISPLAY_ID);
3461 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3462
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003463 mDispatcher->onWindowInfosChanged(
3464 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003465
3466 // Set cursor position in window in default display and check that hover enter and move
3467 // events are generated.
3468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003469 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003470 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3471 AINPUT_SOURCE_MOUSE)
3472 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003473 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003474 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003475 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003476
3477 // Remove all windows in secondary display and check that no event happens on window in
3478 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003479 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3480
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003481 windowDefaultDisplay->assertNoEvents();
3482
3483 // Move cursor position in window in default display and check that only hover move
3484 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003485 mDispatcher->onWindowInfosChanged(
3486 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003488 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003489 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3490 AINPUT_SOURCE_MOUSE)
3491 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003493 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003494 windowDefaultDisplay->consumeMotionEvent(
3495 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3496 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003497 windowDefaultDisplay->assertNoEvents();
3498}
3499
Garfield Tan00f511d2019-06-12 16:55:40 -07003500TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003501 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003502
3503 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003504 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003505 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003506 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003507 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003508 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003509
3510 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3511
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003512 mDispatcher->onWindowInfosChanged(
3513 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003514
3515 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3516 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003518 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003519 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003520 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003521 windowRight->assertNoEvents();
3522}
3523
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003524TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003526 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3527 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003528 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003529
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003530 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003531 setFocusedWindow(window);
3532
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003533 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003534
Prabir Pradhan678438e2023-04-13 19:32:51 +00003535 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003536
3537 // Window should receive key down event.
3538 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3539
3540 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3541 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003542 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003543 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003544 AKEY_EVENT_FLAG_CANCELED);
3545}
3546
3547TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003549 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3550 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003551
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003552 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003553
Prabir Pradhan678438e2023-04-13 19:32:51 +00003554 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3555 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003556
3557 // Window should receive motion down event.
3558 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3559
3560 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3561 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003562 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003563 window->consumeMotionEvent(
3564 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003565}
3566
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003567TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3568 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3569 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3570 "Fake Window", ADISPLAY_ID_DEFAULT);
3571
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003573
3574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3575 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3576 .build());
3577
3578 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3579
3580 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3581 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3582 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3583
3584 // After the device has been reset, a new hovering stream can be sent to the window
3585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3586 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3587 .build());
3588 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3589}
3590
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003591TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3592 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003593 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3594 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003595 window->setFocusable(true);
3596
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003597 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003598 setFocusedWindow(window);
3599
3600 window->consumeFocusEvent(true);
3601
Prabir Pradhan678438e2023-04-13 19:32:51 +00003602 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003603 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3604 const nsecs_t injectTime = keyArgs.eventTime;
3605 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003606 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003607 // The dispatching time should be always greater than or equal to intercept key timeout.
3608 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3609 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3610 std::chrono::nanoseconds(interceptKeyTimeout).count());
3611}
3612
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003613/**
3614 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3615 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003616TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
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
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003622 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003623 setFocusedWindow(window);
3624
3625 window->consumeFocusEvent(true);
3626
Prabir Pradhan678438e2023-04-13 19:32:51 +00003627 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003628 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003629
3630 // Set a value that's significantly larger than the default consumption timeout. If the
3631 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3632 mFakePolicy->setInterceptKeyTimeout(600ms);
3633 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3634 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003635 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3636}
3637
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003638/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003639 * Two windows. First is a regular window. Second does not overlap with the first, and has
3640 * WATCH_OUTSIDE_TOUCH.
3641 * Both windows are owned by the same UID.
3642 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3643 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3644 */
3645TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3647 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3648 "First Window", ADISPLAY_ID_DEFAULT);
3649 window->setFrame(Rect{0, 0, 100, 100});
3650
3651 sp<FakeWindowHandle> outsideWindow =
3652 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3653 ADISPLAY_ID_DEFAULT);
3654 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3655 outsideWindow->setWatchOutsideTouch(true);
3656 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003657 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003658
3659 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003660 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3661 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3662 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003663 window->consumeMotionDown();
3664 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3665 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3666 outsideWindow->consumeMotionEvent(
3667 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3668}
3669
3670/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003671 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3672 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3673 * ACTION_OUTSIDE event is sent per gesture.
3674 */
3675TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3676 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003678 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3679 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003680 window->setWatchOutsideTouch(true);
3681 window->setFrame(Rect{0, 0, 100, 100});
3682 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003683 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3684 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003685 secondWindow->setFrame(Rect{100, 100, 200, 200});
3686 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003687 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3688 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003689 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003690 mDispatcher->onWindowInfosChanged(
3691 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003692
3693 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003694 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3695 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3696 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003697 window->assertNoEvents();
3698 secondWindow->assertNoEvents();
3699
3700 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3701 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003702 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3703 ADISPLAY_ID_DEFAULT,
3704 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003705 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3706 window->consumeMotionEvent(
3707 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003708 secondWindow->consumeMotionDown();
3709 thirdWindow->assertNoEvents();
3710
3711 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3712 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003713 mDispatcher->notifyMotion(
3714 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3715 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003716 window->assertNoEvents();
3717 secondWindow->consumeMotionMove();
3718 thirdWindow->consumeMotionDown();
3719}
3720
Prabir Pradhan814fe082022-07-22 20:22:18 +00003721TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003723 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3724 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003725 window->setFocusable(true);
3726
Patrick Williamsd828f302023-04-28 17:52:08 -05003727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003728 setFocusedWindow(window);
3729
3730 window->consumeFocusEvent(true);
3731
Prabir Pradhan678438e2023-04-13 19:32:51 +00003732 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3733 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3734 mDispatcher->notifyKey(keyDown);
3735 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003736
3737 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3738 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3739
3740 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003741 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003742
3743 window->consumeFocusEvent(false);
3744
Prabir Pradhan678438e2023-04-13 19:32:51 +00003745 mDispatcher->notifyKey(keyDown);
3746 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003747 window->assertNoEvents();
3748}
3749
Arthur Hung96483742022-11-15 03:30:48 +00003750TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3752 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3753 "Fake Window", ADISPLAY_ID_DEFAULT);
3754 // Ensure window is non-split and have some transform.
3755 window->setPreventSplitting(true);
3756 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003758
3759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00003761 {50, 50}))
3762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3763 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3764
3765 const MotionEvent secondFingerDownEvent =
3766 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3767 .displayId(ADISPLAY_ID_DEFAULT)
3768 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003769 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3770 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003771 .build();
3772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003773 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00003774 InputEventInjectionSync::WAIT_FOR_RESULT))
3775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3776
3777 const MotionEvent* event = window->consumeMotion();
3778 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3779 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3780 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3781 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3782 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3783}
3784
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003785/**
3786 * Two windows: a splittable and a non-splittable.
3787 * The non-splittable window shouldn't receive any "incomplete" gestures.
3788 * Send the first pointer to the splittable window, and then touch the non-splittable window.
3789 * The second pointer should be dropped because the initial window is splittable, so it won't get
3790 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
3791 * "incomplete" gestures.
3792 */
3793TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
3794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3795 sp<FakeWindowHandle> leftWindow =
3796 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
3797 ADISPLAY_ID_DEFAULT);
3798 leftWindow->setPreventSplitting(false);
3799 leftWindow->setFrame(Rect(0, 0, 100, 100));
3800 sp<FakeWindowHandle> rightWindow =
3801 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
3802 ADISPLAY_ID_DEFAULT);
3803 rightWindow->setPreventSplitting(true);
3804 rightWindow->setFrame(Rect(100, 100, 200, 200));
3805 mDispatcher->onWindowInfosChanged(
3806 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3807
3808 // Touch down on left, splittable window
3809 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3810 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3811 .build());
3812 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3813
3814 mDispatcher->notifyMotion(
3815 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3816 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3817 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
3818 .build());
3819 leftWindow->assertNoEvents();
3820 rightWindow->assertNoEvents();
3821}
3822
Harry Cuttsb166c002023-05-09 13:06:05 +00003823TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3824 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3825 sp<FakeWindowHandle> window =
3826 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3827 window->setFrame(Rect(0, 0, 400, 400));
3828 sp<FakeWindowHandle> trustedOverlay =
3829 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3830 ADISPLAY_ID_DEFAULT);
3831 trustedOverlay->setSpy(true);
3832 trustedOverlay->setTrustedOverlay(true);
3833
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003834 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003835
3836 // Start a three-finger touchpad swipe
3837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3838 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3839 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3840 .build());
3841 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3842 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3843 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3844 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3845 .build());
3846 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3847 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3848 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3849 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3850 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3851 .build());
3852
3853 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3854 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3855 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3856
3857 // Move the swipe a bit
3858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3859 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3860 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3861 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3862 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3863 .build());
3864
3865 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3866
3867 // End the swipe
3868 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3869 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3870 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3871 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3872 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3873 .build());
3874 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3875 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3876 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3877 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3878 .build());
3879 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3880 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3881 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3882 .build());
3883
3884 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3885 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3886 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3887
3888 window->assertNoEvents();
3889}
3890
3891TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3893 sp<FakeWindowHandle> window =
3894 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3895 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003897
3898 // Start a three-finger touchpad swipe
3899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3900 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3901 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3902 .build());
3903 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3904 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3905 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3906 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3907 .build());
3908 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3909 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3910 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3911 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3912 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3913 .build());
3914
3915 // Move the swipe a bit
3916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3917 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3918 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3919 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3920 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3921 .build());
3922
3923 // End the swipe
3924 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3925 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3926 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3927 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3928 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3929 .build());
3930 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3931 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3932 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3933 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3934 .build());
3935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3936 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3937 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3938 .build());
3939
3940 window->assertNoEvents();
3941}
3942
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003943/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003944 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3945 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003946 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003947 */
3948TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3950 sp<FakeWindowHandle> window =
3951 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3952 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003953 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003954
3955 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3956 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3957 .downTime(baseTime + 10)
3958 .eventTime(baseTime + 10)
3959 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3960 .build());
3961
3962 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3963
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003964 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003965 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003966
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003967 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003968
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003969 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3970 .downTime(baseTime + 10)
3971 .eventTime(baseTime + 30)
3972 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3973 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3974 .build());
3975
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003976 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3977
3978 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003979 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3980 .downTime(baseTime + 10)
3981 .eventTime(baseTime + 40)
3982 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3983 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3984 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003985
3986 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3987
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3989 .downTime(baseTime + 10)
3990 .eventTime(baseTime + 50)
3991 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3992 .build());
3993
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003994 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
3995
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3997 .downTime(baseTime + 60)
3998 .eventTime(baseTime + 60)
3999 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4000 .build());
4001
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004002 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004003}
4004
4005/**
Hu Guo771a7692023-09-17 20:51:08 +08004006 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4007 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4008 * its coordinates should be converted by the transform of the windows of target screen.
4009 */
4010TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4011 // This case will create a window and a spy window on the default display and mirror
4012 // window on the second display. cancel event is sent through spy window pilferPointers
4013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4014
4015 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4016 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4017 spyWindowDefaultDisplay->setTrustedOverlay(true);
4018 spyWindowDefaultDisplay->setSpy(true);
4019
4020 sp<FakeWindowHandle> windowDefaultDisplay =
4021 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4022 ADISPLAY_ID_DEFAULT);
4023 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4024
4025 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4026 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4027
4028 // Add the windows to the dispatcher
4029 mDispatcher->onWindowInfosChanged(
4030 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4031 *windowSecondDisplay->getInfo()},
4032 {},
4033 0,
4034 0});
4035
4036 // Send down to ADISPLAY_ID_DEFAULT
4037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4039 {100, 100}))
4040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4041
4042 spyWindowDefaultDisplay->consumeMotionDown();
4043 windowDefaultDisplay->consumeMotionDown();
4044
4045 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4046
4047 // windowDefaultDisplay gets cancel
4048 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4049 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4050
4051 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4052 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4053 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4054 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4055 EXPECT_EQ(100, event->getX(0));
4056 EXPECT_EQ(100, event->getY(0));
4057}
4058
4059/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004060 * Ensure the correct coordinate spaces are used by InputDispatcher.
4061 *
4062 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4063 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4064 * space.
4065 */
4066class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4067public:
4068 void SetUp() override {
4069 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004070 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004071 }
4072
4073 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4074 gui::DisplayInfo info;
4075 info.displayId = displayId;
4076 info.transform = transform;
4077 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004078 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004079 }
4080
4081 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4082 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004083 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004084 }
4085
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004086 void removeAllWindowsAndDisplays() {
4087 mDisplayInfos.clear();
4088 mWindowInfos.clear();
4089 }
4090
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004091 // Set up a test scenario where the display has a scaled projection and there are two windows
4092 // on the display.
4093 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4094 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4095 // respectively.
4096 ui::Transform displayTransform;
4097 displayTransform.set(2, 0, 0, 4);
4098 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4099
4100 std::shared_ptr<FakeApplicationHandle> application =
4101 std::make_shared<FakeApplicationHandle>();
4102
4103 // Add two windows to the display. Their frames are represented in the display space.
4104 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004105 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4106 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004107 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4108 addWindow(firstWindow);
4109
4110 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004111 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4112 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004113 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4114 addWindow(secondWindow);
4115 return {std::move(firstWindow), std::move(secondWindow)};
4116 }
4117
4118private:
4119 std::vector<gui::DisplayInfo> mDisplayInfos;
4120 std::vector<gui::WindowInfo> mWindowInfos;
4121};
4122
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004123TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004124 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4125 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004126 // selected so that if the hit test was performed with the point and the bounds being in
4127 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004128 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4129 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4130 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004131
4132 firstWindow->consumeMotionDown();
4133 secondWindow->assertNoEvents();
4134}
4135
4136// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4137// the event should be treated as being in the logical display space.
4138TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4139 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4140 // Send down to the first window. The point is represented in the logical display space. The
4141 // point is selected so that if the hit test was done in logical display space, then it would
4142 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004144 PointF{75 * 2, 55 * 4});
4145
4146 firstWindow->consumeMotionDown();
4147 secondWindow->assertNoEvents();
4148}
4149
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004150// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4151// event should be treated as being in the logical display space.
4152TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4153 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4154
4155 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4156 ui::Transform injectedEventTransform;
4157 injectedEventTransform.set(matrix);
4158 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4159 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4160
4161 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4162 .displayId(ADISPLAY_ID_DEFAULT)
4163 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004164 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004165 .x(untransformedPoint.x)
4166 .y(untransformedPoint.y))
4167 .build();
4168 event.transform(matrix);
4169
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004170 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004171 InputEventInjectionSync::WAIT_FOR_RESULT);
4172
4173 firstWindow->consumeMotionDown();
4174 secondWindow->assertNoEvents();
4175}
4176
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004177TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4178 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4179
4180 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004181 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4182 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4183 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004184
4185 firstWindow->assertNoEvents();
4186 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004187 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004188 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4189
4190 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4191 EXPECT_EQ(300, event->getRawX(0));
4192 EXPECT_EQ(880, event->getRawY(0));
4193
4194 // Ensure that the x and y values are in the window's coordinate space.
4195 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4196 // the logical display space. This will be the origin of the window space.
4197 EXPECT_EQ(100, event->getX(0));
4198 EXPECT_EQ(80, event->getY(0));
4199}
4200
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004201/** Ensure consistent behavior of InputDispatcher in all orientations. */
4202class InputDispatcherDisplayOrientationFixture
4203 : public InputDispatcherDisplayProjectionTest,
4204 public ::testing::WithParamInterface<ui::Rotation> {};
4205
4206// This test verifies the touchable region of a window for all rotations of the display by tapping
4207// in different locations on the display, specifically points close to the four corners of a
4208// window.
4209TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4210 constexpr static int32_t displayWidth = 400;
4211 constexpr static int32_t displayHeight = 800;
4212
4213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4214
4215 const auto rotation = GetParam();
4216
4217 // Set up the display with the specified rotation.
4218 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4219 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4220 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4221 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4222 logicalDisplayWidth, logicalDisplayHeight);
4223 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4224
4225 // Create a window with its bounds determined in the logical display.
4226 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4227 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4228 sp<FakeWindowHandle> window =
4229 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4230 window->setFrame(frameInDisplay, displayTransform);
4231 addWindow(window);
4232
4233 // The following points in logical display space should be inside the window.
4234 static const std::array<vec2, 4> insidePoints{
4235 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4236 for (const auto pointInsideWindow : insidePoints) {
4237 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4238 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004239 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4240 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4241 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004242 window->consumeMotionDown();
4243
Prabir Pradhan678438e2023-04-13 19:32:51 +00004244 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4245 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4246 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004247 window->consumeMotionUp();
4248 }
4249
4250 // The following points in logical display space should be outside the window.
4251 static const std::array<vec2, 5> outsidePoints{
4252 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4253 for (const auto pointOutsideWindow : outsidePoints) {
4254 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4255 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004256 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4257 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4258 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004259
Prabir Pradhan678438e2023-04-13 19:32:51 +00004260 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4261 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4262 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004263 }
4264 window->assertNoEvents();
4265}
4266
4267// Run the precision tests for all rotations.
4268INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4269 InputDispatcherDisplayOrientationFixture,
4270 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4271 ui::ROTATION_270),
4272 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4273 return ftl::enum_string(testParamInfo.param);
4274 });
4275
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004276using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4277 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004278
4279class TransferTouchFixture : public InputDispatcherTest,
4280 public ::testing::WithParamInterface<TransferFunction> {};
4281
4282TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004284
4285 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004286 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004287 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4288 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004289 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004290 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004291 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4292 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004293 sp<FakeWindowHandle> wallpaper =
4294 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4295 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004296 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004297 mDispatcher->onWindowInfosChanged(
4298 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004299
4300 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004301 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4302 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004303
Svet Ganov5d3bc372020-01-26 23:11:07 -08004304 // Only the first window should get the down event
4305 firstWindow->consumeMotionDown();
4306 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004307 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004308
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004309 // Transfer touch to the second window
4310 TransferFunction f = GetParam();
4311 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4312 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004313 // The first window gets cancel and the second gets down
4314 firstWindow->consumeMotionCancel();
4315 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004316 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004317
4318 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004319 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4320 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004321 // The first window gets no events and the second gets up
4322 firstWindow->assertNoEvents();
4323 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004324 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004325}
4326
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004327/**
4328 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4329 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4330 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4331 * natural to the user.
4332 * In this test, we are sending a pointer to both spy window and first window. We then try to
4333 * transfer touch to the second window. The dispatcher should identify the first window as the
4334 * one that should lose the gesture, and therefore the action should be to move the gesture from
4335 * the first window to the second.
4336 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4337 * the other API, as well.
4338 */
4339TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4341
4342 // Create a couple of windows + a spy window
4343 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004344 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004345 spyWindow->setTrustedOverlay(true);
4346 spyWindow->setSpy(true);
4347 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004348 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004349 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004350 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004351
4352 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004353 mDispatcher->onWindowInfosChanged(
4354 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004355
4356 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4358 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004359 // Only the first window and spy should get the down event
4360 spyWindow->consumeMotionDown();
4361 firstWindow->consumeMotionDown();
4362
4363 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4364 // if f === 'transferTouch'.
4365 TransferFunction f = GetParam();
4366 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4367 ASSERT_TRUE(success);
4368 // The first window gets cancel and the second gets down
4369 firstWindow->consumeMotionCancel();
4370 secondWindow->consumeMotionDown();
4371
4372 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004373 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4374 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004375 // The first window gets no events and the second+spy get up
4376 firstWindow->assertNoEvents();
4377 spyWindow->consumeMotionUp();
4378 secondWindow->consumeMotionUp();
4379}
4380
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004381TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004383
4384 PointF touchPoint = {10, 10};
4385
4386 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004387 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004388 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4389 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004390 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004391 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004392 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4393 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004394 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004395
4396 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004397 mDispatcher->onWindowInfosChanged(
4398 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004399
4400 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004401 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4402 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4403 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004404 // Only the first window should get the down event
4405 firstWindow->consumeMotionDown();
4406 secondWindow->assertNoEvents();
4407
4408 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004409 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4410 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004411 // Only the first window should get the pointer down event
4412 firstWindow->consumeMotionPointerDown(1);
4413 secondWindow->assertNoEvents();
4414
4415 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004416 TransferFunction f = GetParam();
4417 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4418 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004419 // The first window gets cancel and the second gets down and pointer down
4420 firstWindow->consumeMotionCancel();
4421 secondWindow->consumeMotionDown();
4422 secondWindow->consumeMotionPointerDown(1);
4423
4424 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004425 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4426 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004427 // The first window gets nothing and the second gets pointer up
4428 firstWindow->assertNoEvents();
4429 secondWindow->consumeMotionPointerUp(1);
4430
4431 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004432 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4433 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004434 // The first window gets nothing and the second gets up
4435 firstWindow->assertNoEvents();
4436 secondWindow->consumeMotionUp();
4437}
4438
Arthur Hungc539dbb2022-12-08 07:45:36 +00004439TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4441
4442 // Create a couple of windows
4443 sp<FakeWindowHandle> firstWindow =
4444 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4445 ADISPLAY_ID_DEFAULT);
4446 firstWindow->setDupTouchToWallpaper(true);
4447 sp<FakeWindowHandle> secondWindow =
4448 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4449 ADISPLAY_ID_DEFAULT);
4450 secondWindow->setDupTouchToWallpaper(true);
4451
4452 sp<FakeWindowHandle> wallpaper1 =
4453 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4454 wallpaper1->setIsWallpaper(true);
4455
4456 sp<FakeWindowHandle> wallpaper2 =
4457 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4458 wallpaper2->setIsWallpaper(true);
4459 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004460 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4461 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4462 {},
4463 0,
4464 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004465
4466 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004467 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4468 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004469
4470 // Only the first window should get the down event
4471 firstWindow->consumeMotionDown();
4472 secondWindow->assertNoEvents();
4473 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4474 wallpaper2->assertNoEvents();
4475
4476 // Transfer touch focus to the second window
4477 TransferFunction f = GetParam();
4478 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4479 ASSERT_TRUE(success);
4480
4481 // The first window gets cancel and the second gets down
4482 firstWindow->consumeMotionCancel();
4483 secondWindow->consumeMotionDown();
4484 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4485 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4486
4487 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004488 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4489 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004490 // The first window gets no events and the second gets up
4491 firstWindow->assertNoEvents();
4492 secondWindow->consumeMotionUp();
4493 wallpaper1->assertNoEvents();
4494 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4495}
4496
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004497// For the cases of single pointer touch and two pointers non-split touch, the api's
4498// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4499// for the case where there are multiple pointers split across several windows.
4500INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4501 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004502 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4503 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004504 return dispatcher->transferTouch(destChannelToken,
4505 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004506 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004507 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4508 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004509 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004510 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004511 }));
4512
Svet Ganov5d3bc372020-01-26 23:11:07 -08004513TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004515
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004516 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004517 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4518 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004519 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004520
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004521 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004522 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4523 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004524 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004525
4526 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004527 mDispatcher->onWindowInfosChanged(
4528 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004529
4530 PointF pointInFirst = {300, 200};
4531 PointF pointInSecond = {300, 600};
4532
4533 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4536 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004537 // Only the first window should get the down event
4538 firstWindow->consumeMotionDown();
4539 secondWindow->assertNoEvents();
4540
4541 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004542 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4543 ADISPLAY_ID_DEFAULT,
4544 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004545 // The first window gets a move and the second a down
4546 firstWindow->consumeMotionMove();
4547 secondWindow->consumeMotionDown();
4548
4549 // Transfer touch focus to the second window
4550 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4551 // The first window gets cancel and the new gets pointer down (it already saw down)
4552 firstWindow->consumeMotionCancel();
4553 secondWindow->consumeMotionPointerDown(1);
4554
4555 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004556 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4557 ADISPLAY_ID_DEFAULT,
4558 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004559 // The first window gets nothing and the second gets pointer up
4560 firstWindow->assertNoEvents();
4561 secondWindow->consumeMotionPointerUp(1);
4562
4563 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004564 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4565 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004566 // The first window gets nothing and the second gets up
4567 firstWindow->assertNoEvents();
4568 secondWindow->consumeMotionUp();
4569}
4570
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004571// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4572// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4573// touch is not supported, so the touch should continue on those windows and the transferred-to
4574// window should get nothing.
4575TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4577
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004578 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004579 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4580 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004581 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004582
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004583 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004584 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4585 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004586 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004587
4588 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004589 mDispatcher->onWindowInfosChanged(
4590 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004591
4592 PointF pointInFirst = {300, 200};
4593 PointF pointInSecond = {300, 600};
4594
4595 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004596 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4597 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4598 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004599 // Only the first window should get the down event
4600 firstWindow->consumeMotionDown();
4601 secondWindow->assertNoEvents();
4602
4603 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004604 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4605 ADISPLAY_ID_DEFAULT,
4606 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004607 // The first window gets a move and the second a down
4608 firstWindow->consumeMotionMove();
4609 secondWindow->consumeMotionDown();
4610
4611 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004612 const bool transferred =
4613 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004614 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4615 ASSERT_FALSE(transferred);
4616 firstWindow->assertNoEvents();
4617 secondWindow->assertNoEvents();
4618
4619 // The rest of the dispatch should proceed as normal
4620 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004621 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4622 ADISPLAY_ID_DEFAULT,
4623 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004624 // The first window gets MOVE and the second gets pointer up
4625 firstWindow->consumeMotionMove();
4626 secondWindow->consumeMotionUp();
4627
4628 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004629 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4630 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004631 // The first window gets nothing and the second gets up
4632 firstWindow->consumeMotionUp();
4633 secondWindow->assertNoEvents();
4634}
4635
Arthur Hungabbb9d82021-09-01 14:52:30 +00004636// This case will create two windows and one mirrored window on the default display and mirror
4637// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4638// the windows info of second display before default display.
4639TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4640 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4641 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004642 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004643 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004644 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004645 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004646 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004647
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004648 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004649 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004650
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004651 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004652 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004653
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004654 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004655 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004656
4657 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004658 mDispatcher->onWindowInfosChanged(
4659 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4660 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4661 *secondWindowInPrimary->getInfo()},
4662 {},
4663 0,
4664 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004665
4666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004667 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004668 {50, 50}))
4669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4670
4671 // Window should receive motion event.
4672 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4673
4674 // Transfer touch focus
4675 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4676 secondWindowInPrimary->getToken()));
4677 // The first window gets cancel.
4678 firstWindowInPrimary->consumeMotionCancel();
4679 secondWindowInPrimary->consumeMotionDown();
4680
4681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004682 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004683 ADISPLAY_ID_DEFAULT, {150, 50}))
4684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4685 firstWindowInPrimary->assertNoEvents();
4686 secondWindowInPrimary->consumeMotionMove();
4687
4688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004689 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004690 {150, 50}))
4691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4692 firstWindowInPrimary->assertNoEvents();
4693 secondWindowInPrimary->consumeMotionUp();
4694}
4695
4696// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4697// 'transferTouch' api.
4698TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4700 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004701 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004702 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004703 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004704 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004705 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004706
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004707 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004708 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004709
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004710 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004711 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004712
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004713 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004714 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004715
4716 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004717 mDispatcher->onWindowInfosChanged(
4718 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4719 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4720 *secondWindowInPrimary->getInfo()},
4721 {},
4722 0,
4723 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004724
4725 // Touch on second display.
4726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
4728 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00004729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4730
4731 // Window should receive motion event.
4732 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4733
4734 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004735 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004736
4737 // The first window gets cancel.
4738 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4739 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4740
4741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004742 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004743 SECOND_DISPLAY_ID, {150, 50}))
4744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4745 firstWindowInPrimary->assertNoEvents();
4746 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4747
4748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004749 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00004750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4751 firstWindowInPrimary->assertNoEvents();
4752 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4753}
4754
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004755TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4758 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004759
Vishnu Nair47074b82020-08-14 11:54:47 -07004760 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004761 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004762 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004763
4764 window->consumeFocusEvent(true);
4765
Prabir Pradhan678438e2023-04-13 19:32:51 +00004766 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004767
4768 // Window should receive key down event.
4769 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004770
4771 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004772 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004773 mFakePolicy->assertUserActivityPoked();
4774}
4775
4776TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4778 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4779 "Fake Window", ADISPLAY_ID_DEFAULT);
4780
4781 window->setDisableUserActivity(true);
4782 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004783 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004784 setFocusedWindow(window);
4785
4786 window->consumeFocusEvent(true);
4787
4788 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4789
4790 // Window should receive key down event.
4791 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4792
4793 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004794 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004795 mFakePolicy->assertUserActivityNotPoked();
4796}
4797
4798TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4800 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4801 "Fake Window", ADISPLAY_ID_DEFAULT);
4802
4803 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004804 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004805 setFocusedWindow(window);
4806
4807 window->consumeFocusEvent(true);
4808
4809 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4810 mDispatcher->waitForIdle();
4811
4812 // System key is not passed down
4813 window->assertNoEvents();
4814
4815 // Should have poked user activity
4816 mFakePolicy->assertUserActivityPoked();
4817}
4818
4819TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4821 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4822 "Fake Window", ADISPLAY_ID_DEFAULT);
4823
4824 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004825 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004826 setFocusedWindow(window);
4827
4828 window->consumeFocusEvent(true);
4829
4830 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4831 mDispatcher->waitForIdle();
4832
4833 // System key is not passed down
4834 window->assertNoEvents();
4835
4836 // Should have poked user activity
4837 mFakePolicy->assertUserActivityPoked();
4838}
4839
4840TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4843 "Fake Window", ADISPLAY_ID_DEFAULT);
4844
4845 window->setDisableUserActivity(true);
4846 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004848 setFocusedWindow(window);
4849
4850 window->consumeFocusEvent(true);
4851
4852 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4853 mDispatcher->waitForIdle();
4854
4855 // System key is not passed down
4856 window->assertNoEvents();
4857
4858 // Should have poked user activity
4859 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004860}
4861
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004862TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4863 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4864 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4865 "Fake Window", ADISPLAY_ID_DEFAULT);
4866
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004867 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004868
4869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004870 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004871 ADISPLAY_ID_DEFAULT, {100, 100}))
4872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4873
4874 window->consumeMotionEvent(
4875 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4876
4877 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004878 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004879 mFakePolicy->assertUserActivityPoked();
4880}
4881
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004882TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004884 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4885 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004886
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004887 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004888
Prabir Pradhan678438e2023-04-13 19:32:51 +00004889 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004890 mDispatcher->waitForIdle();
4891
4892 window->assertNoEvents();
4893}
4894
4895// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4896TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004897 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004898 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4899 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004900
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004901 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004902
4903 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004904 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004905 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004906 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4907 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004908
4909 // Window should receive only the motion event
4910 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4911 window->assertNoEvents(); // Key event or focus event will not be received
4912}
4913
arthurhungea3f4fc2020-12-21 23:18:53 +08004914TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4916
arthurhungea3f4fc2020-12-21 23:18:53 +08004917 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004918 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4919 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004920 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004921
arthurhungea3f4fc2020-12-21 23:18:53 +08004922 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004923 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4924 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004925 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004926
4927 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004928 mDispatcher->onWindowInfosChanged(
4929 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08004930
4931 PointF pointInFirst = {300, 200};
4932 PointF pointInSecond = {300, 600};
4933
4934 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004935 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4936 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4937 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004938 // Only the first window should get the down event
4939 firstWindow->consumeMotionDown();
4940 secondWindow->assertNoEvents();
4941
4942 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004943 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4944 ADISPLAY_ID_DEFAULT,
4945 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004946 // The first window gets a move and the second a down
4947 firstWindow->consumeMotionMove();
4948 secondWindow->consumeMotionDown();
4949
4950 // Send pointer cancel to the second window
4951 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004952 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004953 {pointInFirst, pointInSecond});
4954 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004955 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004956 // The first window gets move and the second gets cancel.
4957 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4958 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4959
4960 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004961 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4962 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004963 // The first window gets up and the second gets nothing.
4964 firstWindow->consumeMotionUp();
4965 secondWindow->assertNoEvents();
4966}
4967
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004968TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4970
4971 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004972 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004973 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004974 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4975 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4976 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4977
Harry Cutts33476232023-01-30 19:57:29 +00004978 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004979 window->assertNoEvents();
4980 mDispatcher->waitForIdle();
4981}
4982
chaviwd1c23182019-12-20 18:44:56 -08004983class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004984public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004985 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004986 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004987 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004988 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004989 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004990 }
4991
chaviwd1c23182019-12-20 18:44:56 -08004992 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4993
4994 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004995 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4996 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004997 }
4998
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004999 std::optional<int32_t> receiveEvent() {
5000 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
5001 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005002
5003 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
5004
chaviwd1c23182019-12-20 18:44:56 -08005005 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005006 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08005007 expectedDisplayId, expectedFlags);
5008 }
5009
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005010 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005011 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005012 expectedDisplayId, expectedFlags);
5013 }
5014
chaviwd1c23182019-12-20 18:44:56 -08005015 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005016 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08005017 expectedDisplayId, expectedFlags);
5018 }
5019
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005020 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005021 mInputReceiver->consumeMotionEvent(
5022 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
5023 WithDisplayId(expectedDisplayId),
5024 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005025 }
5026
Arthur Hungfbfa5722021-11-16 02:45:54 +00005027 void consumeMotionPointerDown(int32_t pointerIdx) {
5028 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
5029 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005030 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005031 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00005032 }
5033
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005034 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
Evan Rosky84f07f02021-04-16 10:42:42 -07005035
chaviwd1c23182019-12-20 18:44:56 -08005036 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5037
5038private:
5039 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005040};
5041
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005042using InputDispatcherMonitorTest = InputDispatcherTest;
5043
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005044/**
5045 * Two entities that receive touch: A window, and a global monitor.
5046 * The touch goes to the window, and then the window disappears.
5047 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5048 * for the monitor, as well.
5049 * 1. foregroundWindow
5050 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5051 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005052TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5054 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005055 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005056
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005057 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005058
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005059 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005061 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005062 {100, 200}))
5063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5064
5065 // Both the foreground window and the global monitor should receive the touch down
5066 window->consumeMotionDown();
5067 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5068
5069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005070 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005071 ADISPLAY_ID_DEFAULT, {110, 200}))
5072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5073
5074 window->consumeMotionMove();
5075 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5076
5077 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005078 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005079 window->consumeMotionCancel();
5080 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5081
5082 // If more events come in, there will be no more foreground window to send them to. This will
5083 // cause a cancel for the monitor, as well.
5084 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005085 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005086 ADISPLAY_ID_DEFAULT, {120, 200}))
5087 << "Injection should fail because the window was removed";
5088 window->assertNoEvents();
5089 // Global monitor now gets the cancel
5090 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5091}
5092
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005093TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005095 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5096 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005097 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005098
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005099 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005100
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005102 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005103 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005104 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005105 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005106}
5107
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005108TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5109 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005110
Chris Yea209fde2020-07-22 13:54:51 -07005111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005112 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5113 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005114 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005115
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005117 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005119 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005120 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005121
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005122 // Pilfer pointers from the monitor.
5123 // This should not do anything and the window should continue to receive events.
5124 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005125
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005127 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005128 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005130
5131 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5132 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005133}
5134
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005135TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005136 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005137 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5138 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005139 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005140 window->setWindowOffset(20, 40);
5141 window->setWindowTransform(0, 1, -1, 0);
5142
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005143 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005144
5145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005146 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005147 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5148 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5149 MotionEvent* event = monitor.consumeMotion();
5150 // Even though window has transform, gesture monitor must not.
5151 ASSERT_EQ(ui::Transform(), event->getTransform());
5152}
5153
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005154TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005155 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005156 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005157
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005158 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005159 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005160 << "Injection should fail if there is a monitor, but no touchable window";
5161 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005162}
5163
chaviw81e2bb92019-12-18 15:03:51 -08005164TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005166 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5167 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005168
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005169 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005170
5171 NotifyMotionArgs motionArgs =
5172 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5173 ADISPLAY_ID_DEFAULT);
5174
Prabir Pradhan678438e2023-04-13 19:32:51 +00005175 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005176 // Window should receive motion down event.
5177 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5178
5179 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005180 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005181 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5182 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5183 motionArgs.pointerCoords[0].getX() - 10);
5184
Prabir Pradhan678438e2023-04-13 19:32:51 +00005185 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005186 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005187 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005188}
5189
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005190/**
5191 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5192 * the device default right away. In the test scenario, we check both the default value,
5193 * and the action of enabling / disabling.
5194 */
5195TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005197 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5198 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005199 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005200
5201 // Set focused application.
5202 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005203 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005204
5205 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005206 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005207 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005208 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005209
5210 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005211 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005212 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005213 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005214
5215 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005216 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005217 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005218 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005219 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005220 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005221 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005222 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005223
5224 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005225 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005226 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005227 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005228
5229 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005230 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005231 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005232 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005233 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005234 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005235 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005236 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005237
5238 window->assertNoEvents();
5239}
5240
Gang Wange9087892020-01-07 12:17:14 -05005241TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005242 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005243 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5244 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005245
5246 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005247 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005248
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005249 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005250 setFocusedWindow(window);
5251
Harry Cutts33476232023-01-30 19:57:29 +00005252 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005253
Prabir Pradhan678438e2023-04-13 19:32:51 +00005254 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5255 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005256
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005257 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005258 ASSERT_NE(event, nullptr);
5259
5260 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5261 ASSERT_NE(verified, nullptr);
5262 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5263
5264 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5265 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5266 ASSERT_EQ(keyArgs.source, verified->source);
5267 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5268
5269 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5270
5271 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005272 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005273 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005274 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5275 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5276 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5277 ASSERT_EQ(0, verifiedKey.repeatCount);
5278}
5279
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005280TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005282 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5283 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005284
5285 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5286
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005287 ui::Transform transform;
5288 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5289
5290 gui::DisplayInfo displayInfo;
5291 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5292 displayInfo.transform = transform;
5293
Patrick Williamsd828f302023-04-28 17:52:08 -05005294 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005295
Prabir Pradhan678438e2023-04-13 19:32:51 +00005296 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005297 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5298 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005299 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005300
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005301 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005302 ASSERT_NE(event, nullptr);
5303
5304 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5305 ASSERT_NE(verified, nullptr);
5306 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5307
5308 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5309 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5310 EXPECT_EQ(motionArgs.source, verified->source);
5311 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5312
5313 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5314
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005315 const vec2 rawXY =
5316 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5317 motionArgs.pointerCoords[0].getXYValue());
5318 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5319 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005320 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005321 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005322 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005323 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5324 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5325}
5326
chaviw09c8d2d2020-08-24 15:48:26 -07005327/**
5328 * Ensure that separate calls to sign the same data are generating the same key.
5329 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5330 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5331 * tests.
5332 */
5333TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5334 KeyEvent event = getTestKeyEvent();
5335 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5336
5337 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5338 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5339 ASSERT_EQ(hmac1, hmac2);
5340}
5341
5342/**
5343 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5344 */
5345TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5346 KeyEvent event = getTestKeyEvent();
5347 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5348 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5349
5350 verifiedEvent.deviceId += 1;
5351 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5352
5353 verifiedEvent.source += 1;
5354 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5355
5356 verifiedEvent.eventTimeNanos += 1;
5357 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5358
5359 verifiedEvent.displayId += 1;
5360 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5361
5362 verifiedEvent.action += 1;
5363 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5364
5365 verifiedEvent.downTimeNanos += 1;
5366 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5367
5368 verifiedEvent.flags += 1;
5369 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5370
5371 verifiedEvent.keyCode += 1;
5372 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5373
5374 verifiedEvent.scanCode += 1;
5375 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5376
5377 verifiedEvent.metaState += 1;
5378 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5379
5380 verifiedEvent.repeatCount += 1;
5381 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5382}
5383
Vishnu Nair958da932020-08-21 17:12:37 -07005384TEST_F(InputDispatcherTest, SetFocusedWindow) {
5385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5386 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005387 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005388 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005389 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005390 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5391
5392 // Top window is also focusable but is not granted focus.
5393 windowTop->setFocusable(true);
5394 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005395 mDispatcher->onWindowInfosChanged(
5396 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005397 setFocusedWindow(windowSecond);
5398
5399 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005401 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005402
5403 // Focused window should receive event.
5404 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5405 windowTop->assertNoEvents();
5406}
5407
5408TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5410 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005411 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005412 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5413
5414 window->setFocusable(true);
5415 // Release channel for window is no longer valid.
5416 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005417 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005418 setFocusedWindow(window);
5419
5420 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005421 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005422
5423 // window channel is invalid, so it should not receive any input event.
5424 window->assertNoEvents();
5425}
5426
5427TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5429 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005430 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005431 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005432 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5433
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005434 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005435 setFocusedWindow(window);
5436
5437 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005438 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005439
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005440 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005441 window->assertNoEvents();
5442}
5443
5444TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5446 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005447 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005448 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005449 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5451
5452 windowTop->setFocusable(true);
5453 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005454 mDispatcher->onWindowInfosChanged(
5455 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005456 setFocusedWindow(windowTop);
5457 windowTop->consumeFocusEvent(true);
5458
Chavi Weingarten847e8512023-03-29 00:26:09 +00005459 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005460 mDispatcher->onWindowInfosChanged(
5461 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005462 windowSecond->consumeFocusEvent(true);
5463 windowTop->consumeFocusEvent(false);
5464
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005466 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005467
5468 // Focused window should receive event.
5469 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5470}
5471
Chavi Weingarten847e8512023-03-29 00:26:09 +00005472TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5474 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005475 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005476 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005477 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005478 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5479
5480 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005481 windowSecond->setFocusable(false);
5482 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005483 mDispatcher->onWindowInfosChanged(
5484 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005485 setFocusedWindow(windowTop);
5486 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005487
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005489 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005490
5491 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005492 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005493 windowSecond->assertNoEvents();
5494}
5495
5496TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5497 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5498 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005499 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005500 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005501 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5502 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005503 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5504
5505 window->setFocusable(true);
5506 previousFocusedWindow->setFocusable(true);
5507 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005508 mDispatcher->onWindowInfosChanged(
5509 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005510 setFocusedWindow(previousFocusedWindow);
5511 previousFocusedWindow->consumeFocusEvent(true);
5512
5513 // Requesting focus on invisible window takes focus from currently focused window.
5514 setFocusedWindow(window);
5515 previousFocusedWindow->consumeFocusEvent(false);
5516
5517 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005519 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5520 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005521
5522 // Window does not get focus event or key down.
5523 window->assertNoEvents();
5524
5525 // Window becomes visible.
5526 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005528
5529 // Window receives focus event.
5530 window->consumeFocusEvent(true);
5531 // Focused window receives key down.
5532 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5533}
5534
Vishnu Nair599f1412021-06-21 10:39:58 -07005535TEST_F(InputDispatcherTest, DisplayRemoved) {
5536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5537 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005538 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005539 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5540
5541 // window is granted focus.
5542 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005543 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005544 setFocusedWindow(window);
5545 window->consumeFocusEvent(true);
5546
5547 // When a display is removed window loses focus.
5548 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5549 window->consumeFocusEvent(false);
5550}
5551
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005552/**
5553 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5554 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5555 * of the 'slipperyEnterWindow'.
5556 *
5557 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5558 * a way so that the touched location is no longer covered by the top window.
5559 *
5560 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5561 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5562 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5563 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5564 * with ACTION_DOWN).
5565 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5566 * window moved itself away from the touched location and had Flag::SLIPPERY.
5567 *
5568 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5569 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5570 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5571 *
5572 * In this test, we ensure that the event received by the bottom window has
5573 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5574 */
5575TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005576 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005577 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005578
5579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5580 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5581
5582 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005583 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005584 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005585 // Make sure this one overlaps the bottom window
5586 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5587 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5588 // one. Windows with the same owner are not considered to be occluding each other.
5589 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5590
5591 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005592 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005593 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5594
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005595 mDispatcher->onWindowInfosChanged(
5596 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005597
5598 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005599 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5600 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5601 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005602 slipperyExitWindow->consumeMotionDown();
5603 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005604 mDispatcher->onWindowInfosChanged(
5605 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005606
Prabir Pradhan678438e2023-04-13 19:32:51 +00005607 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5608 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5609 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005610
5611 slipperyExitWindow->consumeMotionCancel();
5612
5613 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5614 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5615}
5616
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005617/**
5618 * Two windows, one on the left and another on the right. The left window is slippery. The right
5619 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5620 * touch moves from the left window into the right window, the gesture should continue to go to the
5621 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5622 * reproduces a crash.
5623 */
5624TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5626
5627 sp<FakeWindowHandle> leftSlipperyWindow =
5628 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5629 leftSlipperyWindow->setSlippery(true);
5630 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5631
5632 sp<FakeWindowHandle> rightDropTouchesWindow =
5633 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5634 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5635 rightDropTouchesWindow->setDropInput(true);
5636
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005637 mDispatcher->onWindowInfosChanged(
5638 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005639
5640 // Start touch in the left window
5641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5642 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5643 .build());
5644 leftSlipperyWindow->consumeMotionDown();
5645
5646 // And move it into the right window
5647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5648 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5649 .build());
5650
5651 // Since the right window isn't eligible to receive input, touch does not slip.
5652 // The left window continues to receive the gesture.
5653 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5654 rightDropTouchesWindow->assertNoEvents();
5655}
5656
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005657TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005658 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5660
5661 sp<FakeWindowHandle> leftWindow =
5662 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5663 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005664 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005665
5666 sp<FakeWindowHandle> rightSpy =
5667 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5668 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005669 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005670 rightSpy->setSpy(true);
5671 rightSpy->setTrustedOverlay(true);
5672
5673 sp<FakeWindowHandle> rightWindow =
5674 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5675 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005676 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005677
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005678 mDispatcher->onWindowInfosChanged(
5679 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005680
5681 // Touch in the left window
5682 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5683 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5684 .build());
5685 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5686 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005687 ASSERT_NO_FATAL_FAILURE(
5688 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005689
5690 // Touch another finger over the right windows
5691 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5692 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5693 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5694 .build());
5695 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5696 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5697 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5698 mDispatcher->waitForIdle();
5699 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005700 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5701 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005702
5703 // Release finger over left window. The UP actions are not treated as device interaction.
5704 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5705 // is part of the UP action, we do not treat this as device interaction.
5706 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5707 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5708 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5709 .build());
5710 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5711 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5712 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5713 mDispatcher->waitForIdle();
5714 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5715
5716 // Move remaining finger
5717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5718 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5719 .build());
5720 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5721 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5722 mDispatcher->waitForIdle();
5723 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005724 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005725
5726 // Release all fingers
5727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5728 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5729 .build());
5730 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5731 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5732 mDispatcher->waitForIdle();
5733 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5734}
5735
5736TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5738
5739 sp<FakeWindowHandle> window =
5740 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5741 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005742 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005743
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005744 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005745 setFocusedWindow(window);
5746 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5747
5748 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5749 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5750 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005751 ASSERT_NO_FATAL_FAILURE(
5752 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005753
5754 // The UP actions are not treated as device interaction.
5755 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5756 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5757 mDispatcher->waitForIdle();
5758 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5759}
5760
Garfield Tan1c7bc862020-01-28 13:24:04 -08005761class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5762protected:
5763 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5764 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5765
Chris Yea209fde2020-07-22 13:54:51 -07005766 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005767 sp<FakeWindowHandle> mWindow;
5768
5769 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005770 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005771 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005772 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005773 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005774 ASSERT_EQ(OK, mDispatcher->start());
5775
5776 setUpWindow();
5777 }
5778
5779 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005780 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005781 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005782
Vishnu Nair47074b82020-08-14 11:54:47 -07005783 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005784 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005785 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005786 mWindow->consumeFocusEvent(true);
5787 }
5788
Chris Ye2ad95392020-09-01 13:44:44 -07005789 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005790 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005791 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005792 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005793 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005794
5795 // Window should receive key down event.
5796 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5797 }
5798
5799 void expectKeyRepeatOnce(int32_t repeatCount) {
5800 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005801 mWindow->consumeKeyEvent(
5802 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08005803 }
5804
Chris Ye2ad95392020-09-01 13:44:44 -07005805 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005806 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005807 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005808 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005809 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005810
5811 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005812 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005813 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005814 }
5815};
5816
5817TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005818 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005819 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5820 expectKeyRepeatOnce(repeatCount);
5821 }
5822}
5823
5824TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005825 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005826 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5827 expectKeyRepeatOnce(repeatCount);
5828 }
Harry Cutts33476232023-01-30 19:57:29 +00005829 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005830 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005831 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5832 expectKeyRepeatOnce(repeatCount);
5833 }
5834}
5835
5836TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005837 sendAndConsumeKeyDown(/*deviceId=*/1);
5838 expectKeyRepeatOnce(/*repeatCount=*/1);
5839 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005840 mWindow->assertNoEvents();
5841}
5842
5843TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005844 sendAndConsumeKeyDown(/*deviceId=*/1);
5845 expectKeyRepeatOnce(/*repeatCount=*/1);
5846 sendAndConsumeKeyDown(/*deviceId=*/2);
5847 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005848 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005849 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005850 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005851 expectKeyRepeatOnce(/*repeatCount=*/2);
5852 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005853 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005854 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005855 mWindow->assertNoEvents();
5856}
5857
5858TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005859 sendAndConsumeKeyDown(/*deviceId=*/1);
5860 expectKeyRepeatOnce(/*repeatCount=*/1);
5861 sendAndConsumeKeyDown(/*deviceId=*/2);
5862 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005863 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005864 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005865 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005866 mWindow->assertNoEvents();
5867}
5868
liushenxiang42232912021-05-21 20:24:09 +08005869TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5870 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005871 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005872 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005873 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5874 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5875 mWindow->assertNoEvents();
5876}
5877
Garfield Tan1c7bc862020-01-28 13:24:04 -08005878TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005879 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005880 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005881 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005882 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005883 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5884 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5885 IdGenerator::getSource(repeatEvent->getId()));
5886 }
5887}
5888
5889TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005890 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005891 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005892
5893 std::unordered_set<int32_t> idSet;
5894 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005895 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005896 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5897 int32_t id = repeatEvent->getId();
5898 EXPECT_EQ(idSet.end(), idSet.find(id));
5899 idSet.insert(id);
5900 }
5901}
5902
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005903/* Test InputDispatcher for MultiDisplay */
5904class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5905public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005906 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005907 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005908
Chris Yea209fde2020-07-22 13:54:51 -07005909 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005910 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005911 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005912
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005913 // Set focus window for primary display, but focused display would be second one.
5914 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005915 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005916 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
5917
Vishnu Nair958da932020-08-21 17:12:37 -07005918 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005919 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005920
Chris Yea209fde2020-07-22 13:54:51 -07005921 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005922 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005923 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005924 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005925 // Set focus display to second one.
5926 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5927 // Set focus window for second display.
5928 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005929 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005930 mDispatcher->onWindowInfosChanged(
5931 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005932 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005933 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005934 }
5935
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005936 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005937 InputDispatcherTest::TearDown();
5938
Chris Yea209fde2020-07-22 13:54:51 -07005939 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005940 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005941 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005942 windowInSecondary.clear();
5943 }
5944
5945protected:
Chris Yea209fde2020-07-22 13:54:51 -07005946 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005947 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005948 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005949 sp<FakeWindowHandle> windowInSecondary;
5950};
5951
5952TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5953 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005955 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005957 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005958 windowInSecondary->assertNoEvents();
5959
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005960 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005962 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005964 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005965 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005966}
5967
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005968TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005969 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005971 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005972 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005973 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005974 windowInSecondary->assertNoEvents();
5975
5976 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005978 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005979 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005980 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005981
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005982 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005983 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08005984
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005985 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005986 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005987 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005988
5989 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005990 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08005991 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005992 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005993 windowInSecondary->assertNoEvents();
5994}
5995
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005996// Test per-display input monitors for motion event.
5997TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005998 FakeMonitorReceiver monitorInPrimary =
5999 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6000 FakeMonitorReceiver monitorInSecondary =
6001 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006002
6003 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006005 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006007 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006008 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006009 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006010 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006011
6012 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006014 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006015 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006016 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006017 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006018 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006019 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006020
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006021 // Lift up the touch from the second display
6022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006023 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6025 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6026 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6027
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006028 // Test inject a non-pointer motion event.
6029 // If specific a display, it will dispatch to the focused window of particular display,
6030 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006032 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006034 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006035 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006036 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006037 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006038}
6039
6040// Test per-display input monitors for key event.
6041TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006042 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006043 FakeMonitorReceiver monitorInPrimary =
6044 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6045 FakeMonitorReceiver monitorInSecondary =
6046 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006047
6048 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006050 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006051 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006052 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006053 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006054 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006055}
6056
Vishnu Nair958da932020-08-21 17:12:37 -07006057TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6058 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006059 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006060 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006061 mDispatcher->onWindowInfosChanged(
6062 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6063 *windowInSecondary->getInfo()},
6064 {},
6065 0,
6066 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006067 setFocusedWindow(secondWindowInPrimary);
6068 windowInPrimary->consumeFocusEvent(false);
6069 secondWindowInPrimary->consumeFocusEvent(true);
6070
6071 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6073 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006074 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006075 windowInPrimary->assertNoEvents();
6076 windowInSecondary->assertNoEvents();
6077 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6078}
6079
Arthur Hungdfd528e2021-12-08 13:23:04 +00006080TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6081 FakeMonitorReceiver monitorInPrimary =
6082 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6083 FakeMonitorReceiver monitorInSecondary =
6084 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6085
6086 // Test touch down on primary display.
6087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006088 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6090 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6091 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6092
6093 // Test touch down on second display.
6094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006095 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006096 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6097 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6098 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6099
6100 // Trigger cancel touch.
6101 mDispatcher->cancelCurrentTouch();
6102 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6103 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6104 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6105 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6106
6107 // Test inject a move motion event, no window/monitor should receive the event.
6108 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006109 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006110 ADISPLAY_ID_DEFAULT, {110, 200}))
6111 << "Inject motion event should return InputEventInjectionResult::FAILED";
6112 windowInPrimary->assertNoEvents();
6113 monitorInPrimary.assertNoEvents();
6114
6115 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006116 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006117 SECOND_DISPLAY_ID, {110, 200}))
6118 << "Inject motion event should return InputEventInjectionResult::FAILED";
6119 windowInSecondary->assertNoEvents();
6120 monitorInSecondary.assertNoEvents();
6121}
6122
Jackal Guof9696682018-10-05 12:23:23 +08006123class InputFilterTest : public InputDispatcherTest {
6124protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006125 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6126 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006127 NotifyMotionArgs motionArgs;
6128
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006129 motionArgs =
6130 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006131 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006132 motionArgs =
6133 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006134 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006135 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006136 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006137 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006138 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006139 } else {
6140 mFakePolicy->assertFilterInputEventWasNotCalled();
6141 }
6142 }
6143
6144 void testNotifyKey(bool expectToBeFiltered) {
6145 NotifyKeyArgs keyArgs;
6146
6147 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006148 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006149 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006150 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006151 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006152
6153 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006154 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006155 } else {
6156 mFakePolicy->assertFilterInputEventWasNotCalled();
6157 }
6158 }
6159};
6160
6161// Test InputFilter for MotionEvent
6162TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6163 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006164 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6165 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006166
6167 // Enable InputFilter
6168 mDispatcher->setInputFilterEnabled(true);
6169 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006170 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6171 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006172
6173 // Disable InputFilter
6174 mDispatcher->setInputFilterEnabled(false);
6175 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006176 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6177 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006178}
6179
6180// Test InputFilter for KeyEvent
6181TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6182 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006183 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006184
6185 // Enable InputFilter
6186 mDispatcher->setInputFilterEnabled(true);
6187 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006188 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006189
6190 // Disable InputFilter
6191 mDispatcher->setInputFilterEnabled(false);
6192 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006193 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006194}
6195
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006196// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6197// logical display coordinate space.
6198TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6199 ui::Transform firstDisplayTransform;
6200 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6201 ui::Transform secondDisplayTransform;
6202 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6203
6204 std::vector<gui::DisplayInfo> displayInfos(2);
6205 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6206 displayInfos[0].transform = firstDisplayTransform;
6207 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6208 displayInfos[1].transform = secondDisplayTransform;
6209
Patrick Williamsd828f302023-04-28 17:52:08 -05006210 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006211
6212 // Enable InputFilter
6213 mDispatcher->setInputFilterEnabled(true);
6214
6215 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006216 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6217 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006218}
6219
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006220class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6221protected:
6222 virtual void SetUp() override {
6223 InputDispatcherTest::SetUp();
6224
6225 /**
6226 * We don't need to enable input filter to test the injected event policy, but we enabled it
6227 * here to make the tests more realistic, since this policy only matters when inputfilter is
6228 * on.
6229 */
6230 mDispatcher->setInputFilterEnabled(true);
6231
6232 std::shared_ptr<InputApplicationHandle> application =
6233 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006234 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6235 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006236
6237 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6238 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006239 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006240 setFocusedWindow(mWindow);
6241 mWindow->consumeFocusEvent(true);
6242 }
6243
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006244 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6245 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006246 KeyEvent event;
6247
6248 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6249 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6250 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006251 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006252 const int32_t additionalPolicyFlags =
6253 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006255 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006256 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006257 policyFlags | additionalPolicyFlags));
6258
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006259 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006260 }
6261
6262 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6263 int32_t flags) {
6264 MotionEvent event;
6265 PointerProperties pointerProperties[1];
6266 PointerCoords pointerCoords[1];
6267 pointerProperties[0].clear();
6268 pointerProperties[0].id = 0;
6269 pointerCoords[0].clear();
6270 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6271 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6272
6273 ui::Transform identityTransform;
6274 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6275 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6276 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6277 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6278 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006279 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006280 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006281 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006282
6283 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006285 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006286 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006287 policyFlags | additionalPolicyFlags));
6288
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006289 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006290 }
6291
6292private:
6293 sp<FakeWindowHandle> mWindow;
6294};
6295
6296TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006297 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6298 // filter. Without it, the event will no different from a regularly injected event, and the
6299 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006300 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6301 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006302}
6303
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006304TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006305 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006306 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006307 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6308}
6309
6310TEST_F(InputFilterInjectionPolicyTest,
6311 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6312 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006313 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006314 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006315}
6316
6317TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006318 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6319 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006320}
6321
chaviwfd6d3512019-03-25 13:23:49 -07006322class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006323 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006324 InputDispatcherTest::SetUp();
6325
Chris Yea209fde2020-07-22 13:54:51 -07006326 std::shared_ptr<FakeApplicationHandle> application =
6327 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006328 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006329 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006330 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006331
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006332 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006333 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006334 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006335
6336 // Set focused application.
6337 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006338 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006339
6340 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006341 mDispatcher->onWindowInfosChanged(
6342 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006343 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006344 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006345 }
6346
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006347 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006348 InputDispatcherTest::TearDown();
6349
6350 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006351 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006352 }
6353
6354protected:
6355 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006356 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006357 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006358};
6359
6360// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6361// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6362// the onPointerDownOutsideFocus callback.
6363TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006365 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006366 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006368 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006369
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006370 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006371 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6372}
6373
6374// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6375// DOWN on the window that doesn't have focus. Ensure no window received the
6376// onPointerDownOutsideFocus callback.
6377TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006379 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6380 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006382 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006383
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006384 ASSERT_TRUE(mDispatcher->waitForIdle());
6385 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006386}
6387
6388// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6389// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6390TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006392 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006393 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006394 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006395
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006396 ASSERT_TRUE(mDispatcher->waitForIdle());
6397 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006398}
6399
6400// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6401// DOWN on the window that already has focus. Ensure no window received the
6402// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006403TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006405 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006406 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006407 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006408 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006409
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006410 ASSERT_TRUE(mDispatcher->waitForIdle());
6411 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006412}
6413
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006414// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6415// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6416TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6417 const MotionEvent event =
6418 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6419 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006420 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006421 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6422 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6425 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6426
6427 ASSERT_TRUE(mDispatcher->waitForIdle());
6428 mFakePolicy->assertOnPointerDownWasNotCalled();
6429 // Ensure that the unfocused window did not receive any FOCUS events.
6430 mUnfocusedWindow->assertNoEvents();
6431}
6432
chaviwaf87b3e2019-10-01 16:59:28 -07006433// These tests ensures we can send touch events to a single client when there are multiple input
6434// windows that point to the same client token.
6435class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6436 virtual void SetUp() override {
6437 InputDispatcherTest::SetUp();
6438
Chris Yea209fde2020-07-22 13:54:51 -07006439 std::shared_ptr<FakeApplicationHandle> application =
6440 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006441 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6442 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006443 mWindow1->setFrame(Rect(0, 0, 100, 100));
6444
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006445 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6446 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006447 mWindow2->setFrame(Rect(100, 100, 200, 200));
6448
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006449 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006450 }
6451
6452protected:
6453 sp<FakeWindowHandle> mWindow1;
6454 sp<FakeWindowHandle> mWindow2;
6455
6456 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006457 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006458 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6459 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006460 }
6461
6462 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6463 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006464 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006465 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006466
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006467 ASSERT_NE(nullptr, motionEvent)
6468 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006469
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006470 assertMotionAction(expectedAction, motionEvent->getAction());
6471 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006472
6473 for (size_t i = 0; i < points.size(); i++) {
6474 float expectedX = points[i].x;
6475 float expectedY = points[i].y;
6476
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006477 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006478 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006479 << ", got " << motionEvent->getX(i);
6480 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006481 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006482 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006483 }
6484 }
chaviw9eaa22c2020-07-01 16:21:27 -07006485
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006486 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006487 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006488 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6489 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006490
6491 // Always consume from window1 since it's the window that has the InputReceiver
6492 consumeMotionEvent(mWindow1, action, expectedPoints);
6493 }
chaviwaf87b3e2019-10-01 16:59:28 -07006494};
6495
6496TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6497 // Touch Window 1
6498 PointF touchedPoint = {10, 10};
6499 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006500 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006501
6502 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006503 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006504
6505 // Touch Window 2
6506 touchedPoint = {150, 150};
6507 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006508 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006509}
6510
chaviw9eaa22c2020-07-01 16:21:27 -07006511TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6512 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006513 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006514 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006515
6516 // Touch Window 1
6517 PointF touchedPoint = {10, 10};
6518 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006519 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006520 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006521 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006522
6523 // Touch Window 2
6524 touchedPoint = {150, 150};
6525 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006526 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6527 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006528
chaviw9eaa22c2020-07-01 16:21:27 -07006529 // Update the transform so rotation is set
6530 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006531 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006532 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6533 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006534}
6535
chaviw9eaa22c2020-07-01 16:21:27 -07006536TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006537 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006538 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006539
6540 // Touch Window 1
6541 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6542 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006543 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006544
6545 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006546 touchedPoints.push_back(PointF{150, 150});
6547 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006548 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006549
chaviw9eaa22c2020-07-01 16:21:27 -07006550 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006551 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006552 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006553
chaviw9eaa22c2020-07-01 16:21:27 -07006554 // Update the transform so rotation is set for Window 2
6555 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006556 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006557 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006558 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006559}
6560
chaviw9eaa22c2020-07-01 16:21:27 -07006561TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006562 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006563 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006564
6565 // Touch Window 1
6566 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6567 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006568 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006569
6570 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006571 touchedPoints.push_back(PointF{150, 150});
6572 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006573
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006574 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006575
6576 // Move both windows
6577 touchedPoints = {{20, 20}, {175, 175}};
6578 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6579 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6580
chaviw9eaa22c2020-07-01 16:21:27 -07006581 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006582
chaviw9eaa22c2020-07-01 16:21:27 -07006583 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006584 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006585 expectedPoints.pop_back();
6586
6587 // Touch Window 2
6588 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006589 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006590 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006591 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006592
6593 // Move both windows
6594 touchedPoints = {{20, 20}, {175, 175}};
6595 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6596 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6597
6598 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006599}
6600
6601TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6602 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006603 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006604
6605 // Touch Window 1
6606 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6607 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006608 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006609
6610 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006611 touchedPoints.push_back(PointF{150, 150});
6612 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006613
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006614 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006615
6616 // Move both windows
6617 touchedPoints = {{20, 20}, {175, 175}};
6618 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6619 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6620
chaviw9eaa22c2020-07-01 16:21:27 -07006621 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006622}
6623
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006624/**
6625 * When one of the windows is slippery, the touch should not slip into the other window with the
6626 * same input channel.
6627 */
6628TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6629 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006630 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006631
6632 // Touch down in window 1
6633 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6634 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6635 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6636
6637 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6638 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6639 // getting generated.
6640 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6641 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6642
6643 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6644}
6645
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006646/**
6647 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6648 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6649 * that the pointer is hovering over may have a different transform.
6650 */
6651TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006652 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006653
6654 // Start hover in window 1
6655 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6656 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6657 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6658 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6659
6660 // Move hover to window 2.
6661 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6662 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6663
6664 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6665 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6666 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6667}
6668
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006669class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6670 virtual void SetUp() override {
6671 InputDispatcherTest::SetUp();
6672
Chris Yea209fde2020-07-22 13:54:51 -07006673 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006674 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006675 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6676 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006677 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006678 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006679 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006680
6681 // Set focused application.
6682 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006684 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006685 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006686 mWindow->consumeFocusEvent(true);
6687 }
6688
6689 virtual void TearDown() override {
6690 InputDispatcherTest::TearDown();
6691 mWindow.clear();
6692 }
6693
6694protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006695 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07006696 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006697 sp<FakeWindowHandle> mWindow;
6698 static constexpr PointF WINDOW_LOCATION = {20, 20};
6699
6700 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006703 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006705 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006706 WINDOW_LOCATION));
6707 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006708
6709 sp<FakeWindowHandle> addSpyWindow() {
6710 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006711 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006712 spy->setTrustedOverlay(true);
6713 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006714 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006715 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006716 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006717 return spy;
6718 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006719};
6720
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006721// Send a tap and respond, which should not cause an ANR.
6722TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6723 tapOnWindow();
6724 mWindow->consumeMotionDown();
6725 mWindow->consumeMotionUp();
6726 ASSERT_TRUE(mDispatcher->waitForIdle());
6727 mFakePolicy->assertNotifyAnrWasNotCalled();
6728}
6729
6730// Send a regular key and respond, which should not cause an ANR.
6731TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006733 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6734 ASSERT_TRUE(mDispatcher->waitForIdle());
6735 mFakePolicy->assertNotifyAnrWasNotCalled();
6736}
6737
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006738TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6739 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006740 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006741 mWindow->consumeFocusEvent(false);
6742
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006743 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006744 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6745 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00006746 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006748 // Key will not go to window because we have no focused window.
6749 // The 'no focused window' ANR timer should start instead.
6750
6751 // Now, the focused application goes away.
6752 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6753 // The key should get dropped and there should be no ANR.
6754
6755 ASSERT_TRUE(mDispatcher->waitForIdle());
6756 mFakePolicy->assertNotifyAnrWasNotCalled();
6757}
6758
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006759// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006760// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6761// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006762TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006764 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006765 WINDOW_LOCATION));
6766
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006767 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6768 ASSERT_TRUE(sequenceNum);
6769 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006770 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006771
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006772 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006773 mWindow->consumeMotionEvent(
6774 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006775 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006776 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006777}
6778
6779// Send a key to the app and have the app not respond right away.
6780TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6781 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006783 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6784 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006785 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006786 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006787 ASSERT_TRUE(mDispatcher->waitForIdle());
6788}
6789
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006790// We have a focused application, but no focused window
6791TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006792 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006793 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006794 mWindow->consumeFocusEvent(false);
6795
6796 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006798 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799 WINDOW_LOCATION));
6800 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6801 mDispatcher->waitForIdle();
6802 mFakePolicy->assertNotifyAnrWasNotCalled();
6803
6804 // Once a focused event arrives, we get an ANR for this application
6805 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6806 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006807 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006808 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006809 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006810 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006811 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006812 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813 ASSERT_TRUE(mDispatcher->waitForIdle());
6814}
6815
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006816/**
6817 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6818 * there will not be an ANR.
6819 */
6820TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6821 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006822 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006823 mWindow->consumeFocusEvent(false);
6824
6825 KeyEvent event;
6826 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6827 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6828
6829 // Define a valid key down event that is stale (too old).
6830 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006831 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006832 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006833
6834 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6835
6836 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006838 InputEventInjectionSync::WAIT_FOR_RESULT,
6839 INJECT_EVENT_TIMEOUT, policyFlags);
6840 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6841 << "Injection should fail because the event is stale";
6842
6843 ASSERT_TRUE(mDispatcher->waitForIdle());
6844 mFakePolicy->assertNotifyAnrWasNotCalled();
6845 mWindow->assertNoEvents();
6846}
6847
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006848// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006849// Make sure that we don't notify policy twice about the same ANR.
6850TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07006851 const std::chrono::duration appTimeout = 400ms;
6852 mApplication->setDispatchingTimeout(appTimeout);
6853 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6854
Vishnu Nair47074b82020-08-14 11:54:47 -07006855 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006856 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006857 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006858
6859 // Once a focused event arrives, we get an ANR for this application
6860 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6861 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07006862 const std::chrono::duration eventInjectionTimeout = 100ms;
6863 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006864 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006865 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07006866 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
6867 /*allowKeyRepeat=*/false);
6868 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
6869 << "result=" << ftl::enum_string(result);
6870 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
6871 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
6872 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
6873 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006874
Vishnu Naire4df8752022-09-08 09:17:55 -07006875 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006876 // ANR should not be raised again. It is up to policy to do that if it desires.
6877 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006878
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006879 // If we now get a focused window, the ANR should stop, but the policy handles that via
6880 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006881 ASSERT_TRUE(mDispatcher->waitForIdle());
6882}
6883
6884// We have a focused application, but no focused window
6885TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006886 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006887 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888 mWindow->consumeFocusEvent(false);
6889
6890 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006891 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006892
Vishnu Naire4df8752022-09-08 09:17:55 -07006893 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6894 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006895
6896 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006897 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006898 ASSERT_TRUE(mDispatcher->waitForIdle());
6899 mWindow->assertNoEvents();
6900}
6901
6902/**
6903 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6904 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6905 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6906 * the ANR mechanism should still work.
6907 *
6908 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6909 * DOWN event, while not responding on the second one.
6910 */
6911TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6912 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006913 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6915 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6916 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006917 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006918
6919 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006920 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6922 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6923 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006924 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925
6926 // We have now sent down and up. Let's consume first event and then ANR on the second.
6927 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6928 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006929 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006930}
6931
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006932// A spy window can receive an ANR
6933TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6934 sp<FakeWindowHandle> spy = addSpyWindow();
6935
6936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006937 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006938 WINDOW_LOCATION));
6939 mWindow->consumeMotionDown();
6940
6941 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6942 ASSERT_TRUE(sequenceNum);
6943 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006944 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006945
6946 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006947 spy->consumeMotionEvent(
6948 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006949 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006950 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006951}
6952
6953// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006954// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006955TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6956 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006957
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006959 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006960 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006962
6963 // Stuck on the 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
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006967 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006968 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006969 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6970 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006971
6972 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6973 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006974 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006975 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006976 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006977}
6978
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006979// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006980// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006981TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6982 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006983
6984 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006985 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6986 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006987
6988 mWindow->consumeMotionDown();
6989 // Stuck on the ACTION_UP
6990 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006991 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006992
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006993 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006994 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006995 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6996 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006997
6998 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6999 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007000 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007001 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007002 spy->assertNoEvents();
7003}
7004
7005TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007006 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007007
7008 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7009
7010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007011 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007012 WINDOW_LOCATION));
7013
7014 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7015 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7016 ASSERT_TRUE(consumeSeq);
7017
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007018 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7019 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007020
7021 monitor.finishEvent(*consumeSeq);
7022 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7023
7024 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007025 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007026}
7027
7028// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7029// process events, you don't get an anr. When the window later becomes unresponsive again, you
7030// get an ANR again.
7031// 1. tap -> block on ACTION_UP -> receive ANR
7032// 2. consume all pending events (= queue becomes healthy again)
7033// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7034TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7035 tapOnWindow();
7036
7037 mWindow->consumeMotionDown();
7038 // Block on ACTION_UP
7039 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007040 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007041 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7042 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007043 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007044 mWindow->assertNoEvents();
7045
7046 tapOnWindow();
7047 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007048 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007049 mWindow->consumeMotionUp();
7050
7051 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007052 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007053 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007054 mWindow->assertNoEvents();
7055}
7056
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007057// If a connection remains unresponsive for a while, make sure policy is only notified once about
7058// it.
7059TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007061 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007062 WINDOW_LOCATION));
7063
7064 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007065 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007066 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007067 // 'notifyConnectionUnresponsive' should only be called once per connection
7068 mFakePolicy->assertNotifyAnrWasNotCalled();
7069 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007070 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007071 mWindow->consumeMotionEvent(
7072 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007073 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007074 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007075 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007076 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007077}
7078
7079/**
7080 * If a window is processing a motion event, and then a key event comes in, the key event should
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007081 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007082 *
7083 * Warning!!!
7084 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7085 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007086 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007087 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7088 *
7089 * If that value changes, this test should also change.
7090 */
7091TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7092 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007093 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007094
7095 tapOnWindow();
7096 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7097 ASSERT_TRUE(downSequenceNum);
7098 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7099 ASSERT_TRUE(upSequenceNum);
7100 // Don't finish the events yet, and send a key
7101 // Injection will "succeed" because we will eventually give up and send the key to the focused
7102 // window even if motions are still being processed. But because the injection timeout is short,
7103 // we will receive INJECTION_TIMED_OUT as the result.
7104
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007105 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007106 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7107 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007108 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007109 // Key will not be sent to the window, yet, because the window is still processing events
7110 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007111 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7112 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7113 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7114 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007115
7116 std::this_thread::sleep_for(500ms);
7117 // if we wait long enough though, dispatcher will give up, and still send the key
7118 // to the focused window, even though we have not yet finished the motion event
7119 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7120 mWindow->finishEvent(*downSequenceNum);
7121 mWindow->finishEvent(*upSequenceNum);
7122}
7123
7124/**
7125 * If a window is processing a motion event, and then a key event comes in, the key event should
7126 * not go to the focused window until the motion is processed.
7127 * If then a new motion comes in, then the pending key event should be going to the currently
7128 * focused window right away.
7129 */
7130TEST_F(InputDispatcherSingleWindowAnr,
7131 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7132 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007133 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007134
7135 tapOnWindow();
7136 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7137 ASSERT_TRUE(downSequenceNum);
7138 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7139 ASSERT_TRUE(upSequenceNum);
7140 // Don't finish the events yet, and send a key
7141 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007143 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7144 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007146 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7147 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7148 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7149 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007150
7151 // Now tap down again. It should cause the pending key to go to the focused window right away.
7152 tapOnWindow();
7153 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7154 // the other events yet. We can finish events in any order.
7155 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7156 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7157 mWindow->consumeMotionDown();
7158 mWindow->consumeMotionUp();
7159 mWindow->assertNoEvents();
7160}
7161
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007162/**
7163 * Send an event to the app and have the app not respond right away.
7164 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7165 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7166 * At some point, the window becomes responsive again.
7167 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7168 */
7169TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7170 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7171 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7172 .build());
7173
7174 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7175 ASSERT_TRUE(sequenceNum);
7176 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7177 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7178
7179 mWindow->finishEvent(*sequenceNum);
7180 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7181 ASSERT_TRUE(mDispatcher->waitForIdle());
7182 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7183
7184 // Now that the window is responsive, let's continue the gesture.
7185 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7186 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7187 .build());
7188
7189 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7190 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7191 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7192 .build());
7193
7194 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7195 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7196 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7197 .build());
7198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7199 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7200 .build());
7201 // We already canceled this pointer, so the window shouldn't get any new events.
7202 mWindow->assertNoEvents();
7203
7204 // Start another one.
7205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7206 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7207 .build());
7208 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7209}
7210
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007211class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7212 virtual void SetUp() override {
7213 InputDispatcherTest::SetUp();
7214
Chris Yea209fde2020-07-22 13:54:51 -07007215 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007216 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007217 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7218 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007219 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007220 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007221 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007222
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007223 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7224 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007225 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007226 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007227
7228 // Set focused application.
7229 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007230 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007231
7232 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007233 mDispatcher->onWindowInfosChanged(
7234 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007235 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007236 mFocusedWindow->consumeFocusEvent(true);
7237 }
7238
7239 virtual void TearDown() override {
7240 InputDispatcherTest::TearDown();
7241
7242 mUnfocusedWindow.clear();
7243 mFocusedWindow.clear();
7244 }
7245
7246protected:
Chris Yea209fde2020-07-22 13:54:51 -07007247 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007248 sp<FakeWindowHandle> mUnfocusedWindow;
7249 sp<FakeWindowHandle> mFocusedWindow;
7250 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7251 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7252 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7253
7254 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7255
7256 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7257
7258private:
7259 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007261 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007262 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007264 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007265 location));
7266 }
7267};
7268
7269// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7270// should be ANR'd first.
7271TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007273 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007274 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007275 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007276 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007277 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007278 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279 // We consumed all events, so no ANR
7280 ASSERT_TRUE(mDispatcher->waitForIdle());
7281 mFakePolicy->assertNotifyAnrWasNotCalled();
7282
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007284 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007285 FOCUSED_WINDOW_LOCATION));
7286 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7287 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007288
7289 const std::chrono::duration timeout =
7290 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007291 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007292 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7293 // sequence to make it consistent
7294 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007295 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007296 mFocusedWindow->consumeMotionDown();
7297 // This cancel is generated because the connection was unresponsive
7298 mFocusedWindow->consumeMotionCancel();
7299 mFocusedWindow->assertNoEvents();
7300 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007301 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007302 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7303 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007304 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007305}
7306
7307// If we have 2 windows with identical timeouts that are both unresponsive,
7308// it doesn't matter which order they should have ANR.
7309// But we should receive ANR for both.
7310TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7311 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007312 mUnfocusedWindow->setDispatchingTimeout(
7313 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007314 mDispatcher->onWindowInfosChanged(
7315 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007316
7317 tapOnFocusedWindow();
7318 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007319 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007320 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7321 mFocusedWindow->getDispatchingTimeout(
7322 DISPATCHING_TIMEOUT)),
7323 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7324
7325 ASSERT_THAT(anrConnectionTokens,
7326 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7327 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007328
7329 ASSERT_TRUE(mDispatcher->waitForIdle());
7330 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007331
7332 mFocusedWindow->consumeMotionDown();
7333 mFocusedWindow->consumeMotionUp();
7334 mUnfocusedWindow->consumeMotionOutside();
7335
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007336 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7337 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007338
7339 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007340 ASSERT_THAT(responsiveTokens,
7341 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7342 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007343 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007344}
7345
7346// If a window is already not responding, the second tap on the same window should be ignored.
7347// We should also log an error to account for the dropped event (not tested here).
7348// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7349TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7350 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007351 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007352 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007353 // Receive the events, but don't respond
7354 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7355 ASSERT_TRUE(downEventSequenceNum);
7356 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7357 ASSERT_TRUE(upEventSequenceNum);
7358 const std::chrono::duration timeout =
7359 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007360 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007361
7362 // Tap once again
7363 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007364 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007365 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007366 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007367 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007368 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007369 FOCUSED_WINDOW_LOCATION));
7370 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7371 // valid touch target
7372 mUnfocusedWindow->assertNoEvents();
7373
7374 // Consume the first tap
7375 mFocusedWindow->finishEvent(*downEventSequenceNum);
7376 mFocusedWindow->finishEvent(*upEventSequenceNum);
7377 ASSERT_TRUE(mDispatcher->waitForIdle());
7378 // The second tap did not go to the focused window
7379 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007380 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007381 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7382 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007383 mFakePolicy->assertNotifyAnrWasNotCalled();
7384}
7385
7386// If you tap outside of all windows, there will not be ANR
7387TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007388 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007389 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007390 LOCATION_OUTSIDE_ALL_WINDOWS));
7391 ASSERT_TRUE(mDispatcher->waitForIdle());
7392 mFakePolicy->assertNotifyAnrWasNotCalled();
7393}
7394
7395// Since the focused window is paused, tapping on it should not produce any events
7396TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7397 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007398 mDispatcher->onWindowInfosChanged(
7399 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007400
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007401 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007402 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007403 FOCUSED_WINDOW_LOCATION));
7404
7405 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7406 ASSERT_TRUE(mDispatcher->waitForIdle());
7407 // Should not ANR because the window is paused, and touches shouldn't go to it
7408 mFakePolicy->assertNotifyAnrWasNotCalled();
7409
7410 mFocusedWindow->assertNoEvents();
7411 mUnfocusedWindow->assertNoEvents();
7412}
7413
7414/**
7415 * If a window is processing a motion event, and then a key event comes in, the key event should
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007416 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007417 * If a different window becomes focused at this time, the key should go to that window instead.
7418 *
7419 * Warning!!!
7420 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7421 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007422 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007423 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7424 *
7425 * If that value changes, this test should also change.
7426 */
7427TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7428 // Set a long ANR timeout to prevent it from triggering
7429 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007430 mDispatcher->onWindowInfosChanged(
7431 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007432
7433 tapOnUnfocusedWindow();
7434 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7435 ASSERT_TRUE(downSequenceNum);
7436 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7437 ASSERT_TRUE(upSequenceNum);
7438 // Don't finish the events yet, and send a key
7439 // Injection will succeed because we will eventually give up and send the key to the focused
7440 // window even if motions are still being processed.
7441
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007442 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007443 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7444 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007446 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007447 // and the key remains pending, waiting for the touch events to be processed.
7448 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7449 // under the hood.
7450 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7451 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007452
7453 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007454 mFocusedWindow->setFocusable(false);
7455 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007456 mDispatcher->onWindowInfosChanged(
7457 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007458 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007459
7460 // Focus events should precede the key events
7461 mUnfocusedWindow->consumeFocusEvent(true);
7462 mFocusedWindow->consumeFocusEvent(false);
7463
7464 // Finish the tap events, which should unblock dispatcher
7465 mUnfocusedWindow->finishEvent(*downSequenceNum);
7466 mUnfocusedWindow->finishEvent(*upSequenceNum);
7467
7468 // Now that all queues are cleared and no backlog in the connections, the key event
7469 // can finally go to the newly focused "mUnfocusedWindow".
7470 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7471 mFocusedWindow->assertNoEvents();
7472 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007473 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007474}
7475
7476// When the touch stream is split across 2 windows, and one of them does not respond,
7477// then ANR should be raised and the touch should be canceled for the unresponsive window.
7478// The other window should not be affected by that.
7479TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7480 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007481 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7482 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7483 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007484 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007485 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007486
7487 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007488 mDispatcher->notifyMotion(
7489 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7490 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007491
7492 const std::chrono::duration timeout =
7493 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007494 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007495
7496 mUnfocusedWindow->consumeMotionDown();
7497 mFocusedWindow->consumeMotionDown();
7498 // Focused window may or may not receive ACTION_MOVE
7499 // But it should definitely receive ACTION_CANCEL due to the ANR
7500 InputEvent* event;
7501 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7502 ASSERT_TRUE(moveOrCancelSequenceNum);
7503 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7504 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007505 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007506 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7507 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7508 mFocusedWindow->consumeMotionCancel();
7509 } else {
7510 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7511 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007512 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007513 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7514 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007515
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007516 mUnfocusedWindow->assertNoEvents();
7517 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007518 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007519}
7520
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007521/**
7522 * If we have no focused window, and a key comes in, we start the ANR timer.
7523 * The focused application should add a focused window before the timer runs out to prevent ANR.
7524 *
7525 * If the user touches another application during this time, the key should be dropped.
7526 * Next, if a new focused window comes in, without toggling the focused application,
7527 * then no ANR should occur.
7528 *
7529 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7530 * but in some cases the policy may not update the focused application.
7531 */
7532TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7533 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7534 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007535 focusedApplication->setDispatchingTimeout(200ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007536 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7537 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7538 mFocusedWindow->setFocusable(false);
7539
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007540 mDispatcher->onWindowInfosChanged(
7541 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007542 mFocusedWindow->consumeFocusEvent(false);
7543
7544 // Send a key. The ANR timer should start because there is no focused window.
7545 // 'focusedApplication' will get blamed if this timer completes.
7546 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007547 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007548 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7549 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00007550 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007552
7553 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7554 // then the injected touches won't cause the focused event to get dropped.
7555 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7556 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7557 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7558 // For this test, it means that the key would get delivered to the window once it becomes
7559 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007560 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007561
7562 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007563 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7564 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7565 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007566
7567 // We do not consume the motion right away, because that would require dispatcher to first
7568 // process (== drop) the key event, and by that time, ANR will be raised.
7569 // Set the focused window first.
7570 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007571 mDispatcher->onWindowInfosChanged(
7572 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007573 setFocusedWindow(mFocusedWindow);
7574 mFocusedWindow->consumeFocusEvent(true);
7575 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7576 // to another application. This could be a bug / behaviour in the policy.
7577
7578 mUnfocusedWindow->consumeMotionDown();
7579
7580 ASSERT_TRUE(mDispatcher->waitForIdle());
7581 // Should not ANR because we actually have a focused window. It was just added too slowly.
7582 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7583}
7584
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007585// These tests ensure we cannot send touch events to a window that's positioned behind a window
7586// that has feature NO_INPUT_CHANNEL.
7587// Layout:
7588// Top (closest to user)
7589// mNoInputWindow (above all windows)
7590// mBottomWindow
7591// Bottom (furthest from user)
7592class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7593 virtual void SetUp() override {
7594 InputDispatcherTest::SetUp();
7595
7596 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007597 mNoInputWindow =
7598 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7599 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007600 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007601 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007602 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7603 // It's perfectly valid for this window to not have an associated input channel
7604
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007605 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7606 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007607 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7608
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007609 mDispatcher->onWindowInfosChanged(
7610 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007611 }
7612
7613protected:
7614 std::shared_ptr<FakeApplicationHandle> mApplication;
7615 sp<FakeWindowHandle> mNoInputWindow;
7616 sp<FakeWindowHandle> mBottomWindow;
7617};
7618
7619TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7620 PointF touchedPoint = {10, 10};
7621
Prabir Pradhan678438e2023-04-13 19:32:51 +00007622 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7623 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7624 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007625
7626 mNoInputWindow->assertNoEvents();
7627 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7628 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7629 // and therefore should prevent mBottomWindow from receiving touches
7630 mBottomWindow->assertNoEvents();
7631}
7632
7633/**
7634 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7635 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7636 */
7637TEST_F(InputDispatcherMultiWindowOcclusionTests,
7638 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007639 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7640 "Window with input channel and NO_INPUT_CHANNEL",
7641 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007642
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007643 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007644 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007645 mDispatcher->onWindowInfosChanged(
7646 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007647
7648 PointF touchedPoint = {10, 10};
7649
Prabir Pradhan678438e2023-04-13 19:32:51 +00007650 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7651 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7652 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007653
7654 mNoInputWindow->assertNoEvents();
7655 mBottomWindow->assertNoEvents();
7656}
7657
Vishnu Nair958da932020-08-21 17:12:37 -07007658class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7659protected:
7660 std::shared_ptr<FakeApplicationHandle> mApp;
7661 sp<FakeWindowHandle> mWindow;
7662 sp<FakeWindowHandle> mMirror;
7663
7664 virtual void SetUp() override {
7665 InputDispatcherTest::SetUp();
7666 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007667 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7668 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7669 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007670 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7671 mWindow->setFocusable(true);
7672 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007673 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007674 }
7675};
7676
7677TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7678 // Request focus on a mirrored window
7679 setFocusedWindow(mMirror);
7680
7681 // window gets focused
7682 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007684 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007685 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7686}
7687
7688// A focused & mirrored window remains focused only if the window and its mirror are both
7689// focusable.
7690TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7691 setFocusedWindow(mMirror);
7692
7693 // window gets focused
7694 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007696 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007697 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007699 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007700 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7701
7702 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007703 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007704
7705 // window loses focus since one of the windows associated with the token in not focusable
7706 mWindow->consumeFocusEvent(false);
7707
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007708 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007709 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007710 mWindow->assertNoEvents();
7711}
7712
7713// A focused & mirrored window remains focused until the window and its mirror both become
7714// invisible.
7715TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7716 setFocusedWindow(mMirror);
7717
7718 // window gets focused
7719 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007721 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007722 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007724 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007725 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7726
7727 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007728 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007729
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007731 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007732 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007734 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007735 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7736
7737 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007738 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007739
7740 // window loses focus only after all windows associated with the token become invisible.
7741 mWindow->consumeFocusEvent(false);
7742
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007743 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007744 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007745 mWindow->assertNoEvents();
7746}
7747
7748// A focused & mirrored window remains focused until both windows are removed.
7749TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7750 setFocusedWindow(mMirror);
7751
7752 // window gets focused
7753 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007755 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007756 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007758 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007759 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7760
7761 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007762 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007763
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007765 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007766 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007768 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007769 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7770
7771 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007772 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007773 mWindow->consumeFocusEvent(false);
7774
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007775 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007776 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007777 mWindow->assertNoEvents();
7778}
7779
7780// Focus request can be pending until one window becomes visible.
7781TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7782 // Request focus on an invisible mirror.
7783 mWindow->setVisible(false);
7784 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007785 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007786 setFocusedWindow(mMirror);
7787
7788 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007790 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7791 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007792
7793 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007794 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007795
7796 // window gets focused
7797 mWindow->consumeFocusEvent(true);
7798 // window gets the pending key event
7799 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7800}
Prabir Pradhan99987712020-11-10 18:43:05 -08007801
7802class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7803protected:
7804 std::shared_ptr<FakeApplicationHandle> mApp;
7805 sp<FakeWindowHandle> mWindow;
7806 sp<FakeWindowHandle> mSecondWindow;
7807
7808 void SetUp() override {
7809 InputDispatcherTest::SetUp();
7810 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007811 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007812 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007813 mSecondWindow =
7814 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007815 mSecondWindow->setFocusable(true);
7816
7817 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007818 mDispatcher->onWindowInfosChanged(
7819 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08007820
7821 setFocusedWindow(mWindow);
7822 mWindow->consumeFocusEvent(true);
7823 }
7824
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007825 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007826 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007827 }
7828
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007829 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7830 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007831 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007832 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7833 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007834 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007835 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007836 }
7837};
7838
7839TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7840 // Ensure that capture cannot be obtained for unfocused windows.
7841 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7842 mFakePolicy->assertSetPointerCaptureNotCalled();
7843 mSecondWindow->assertNoEvents();
7844
7845 // Ensure that capture can be enabled from the focus window.
7846 requestAndVerifyPointerCapture(mWindow, true);
7847
7848 // Ensure that capture cannot be disabled from a window that does not have capture.
7849 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7850 mFakePolicy->assertSetPointerCaptureNotCalled();
7851
7852 // Ensure that capture can be disabled from the window with capture.
7853 requestAndVerifyPointerCapture(mWindow, false);
7854}
7855
7856TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007857 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007858
7859 setFocusedWindow(mSecondWindow);
7860
7861 // Ensure that the capture disabled event was sent first.
7862 mWindow->consumeCaptureEvent(false);
7863 mWindow->consumeFocusEvent(false);
7864 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007865 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007866
7867 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007868 notifyPointerCaptureChanged({});
7869 notifyPointerCaptureChanged(request);
7870 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007871 mWindow->assertNoEvents();
7872 mSecondWindow->assertNoEvents();
7873 mFakePolicy->assertSetPointerCaptureNotCalled();
7874}
7875
7876TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007877 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007878
7879 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007880 notifyPointerCaptureChanged({});
7881 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007882
7883 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007884 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007885 mWindow->consumeCaptureEvent(false);
7886 mWindow->assertNoEvents();
7887}
7888
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007889TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7890 requestAndVerifyPointerCapture(mWindow, true);
7891
7892 // The first window loses focus.
7893 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007894 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007895 mWindow->consumeCaptureEvent(false);
7896
7897 // Request Pointer Capture from the second window before the notification from InputReader
7898 // arrives.
7899 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007900 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007901
7902 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007903 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007904
7905 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007906 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007907
7908 mSecondWindow->consumeFocusEvent(true);
7909 mSecondWindow->consumeCaptureEvent(true);
7910}
7911
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007912TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7913 // App repeatedly enables and disables capture.
7914 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7915 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7916 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7917 mFakePolicy->assertSetPointerCaptureCalled(false);
7918 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7919 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7920
7921 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7922 // first request is now stale, this should do nothing.
7923 notifyPointerCaptureChanged(firstRequest);
7924 mWindow->assertNoEvents();
7925
7926 // InputReader notifies that the second request was enabled.
7927 notifyPointerCaptureChanged(secondRequest);
7928 mWindow->consumeCaptureEvent(true);
7929}
7930
Prabir Pradhan7092e262022-05-03 16:51:09 +00007931TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7932 requestAndVerifyPointerCapture(mWindow, true);
7933
7934 // App toggles pointer capture off and on.
7935 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7936 mFakePolicy->assertSetPointerCaptureCalled(false);
7937
7938 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7939 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7940
7941 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7942 // preceding "disable" request.
7943 notifyPointerCaptureChanged(enableRequest);
7944
7945 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7946 // any notifications.
7947 mWindow->assertNoEvents();
7948}
7949
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007950class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7951protected:
7952 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007953
7954 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7955 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7956
7957 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7958 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7959
7960 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7961 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7962 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7963 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7964 MAXIMUM_OBSCURING_OPACITY);
7965
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007966 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7967 static constexpr gui::Uid APP_B_UID{10002};
7968 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007969
7970 sp<FakeWindowHandle> mTouchWindow;
7971
7972 virtual void SetUp() override {
7973 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007974 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007975 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7976 }
7977
7978 virtual void TearDown() override {
7979 InputDispatcherTest::TearDown();
7980 mTouchWindow.clear();
7981 }
7982
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007983 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007984 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007985 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007986 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007987 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007988 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007989 return window;
7990 }
7991
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007992 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007993 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7994 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007995 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007996 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007997 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007998 return window;
7999 }
8000
8001 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008002 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8003 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8004 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008005 }
8006};
8007
8008TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008009 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008010 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008011 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008012
8013 touch();
8014
8015 mTouchWindow->assertNoEvents();
8016}
8017
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008018TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008019 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8020 const sp<FakeWindowHandle>& w =
8021 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008022 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008023
8024 touch();
8025
8026 mTouchWindow->assertNoEvents();
8027}
8028
8029TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008030 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8031 const sp<FakeWindowHandle>& w =
8032 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008033 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008034
8035 touch();
8036
8037 w->assertNoEvents();
8038}
8039
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008040TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008041 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008042 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008043
8044 touch();
8045
8046 mTouchWindow->consumeAnyMotionDown();
8047}
8048
8049TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008050 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008051 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008052 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008053 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008054
8055 touch({PointF{100, 100}});
8056
8057 mTouchWindow->consumeAnyMotionDown();
8058}
8059
8060TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008061 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008062 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008063 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008064
8065 touch();
8066
8067 mTouchWindow->consumeAnyMotionDown();
8068}
8069
8070TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8071 const sp<FakeWindowHandle>& w =
8072 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008073 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008074
8075 touch();
8076
8077 mTouchWindow->consumeAnyMotionDown();
8078}
8079
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008080TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8081 const sp<FakeWindowHandle>& w =
8082 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008083 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008084
8085 touch();
8086
8087 w->assertNoEvents();
8088}
8089
8090/**
8091 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8092 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8093 * window, the occluding window will still receive ACTION_OUTSIDE event.
8094 */
8095TEST_F(InputDispatcherUntrustedTouchesTest,
8096 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8097 const sp<FakeWindowHandle>& w =
8098 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008099 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008100 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008101
8102 touch();
8103
8104 w->consumeMotionOutside();
8105}
8106
8107TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8108 const sp<FakeWindowHandle>& w =
8109 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008110 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008111 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008112
8113 touch();
8114
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008115 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008116}
8117
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008118TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008119 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008120 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8121 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008122 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008123
8124 touch();
8125
8126 mTouchWindow->consumeAnyMotionDown();
8127}
8128
8129TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8130 const sp<FakeWindowHandle>& w =
8131 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8132 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008133 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008134
8135 touch();
8136
8137 mTouchWindow->consumeAnyMotionDown();
8138}
8139
8140TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008141 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008142 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8143 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008144 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008145
8146 touch();
8147
8148 mTouchWindow->assertNoEvents();
8149}
8150
8151TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8152 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8153 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008154 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8155 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008156 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008157 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8158 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008159 mDispatcher->onWindowInfosChanged(
8160 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008161
8162 touch();
8163
8164 mTouchWindow->assertNoEvents();
8165}
8166
8167TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8168 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8169 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008170 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8171 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008172 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008173 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8174 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008175 mDispatcher->onWindowInfosChanged(
8176 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008177
8178 touch();
8179
8180 mTouchWindow->consumeAnyMotionDown();
8181}
8182
8183TEST_F(InputDispatcherUntrustedTouchesTest,
8184 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8185 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008186 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8187 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008188 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008189 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8190 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008191 mDispatcher->onWindowInfosChanged(
8192 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008193
8194 touch();
8195
8196 mTouchWindow->consumeAnyMotionDown();
8197}
8198
8199TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8200 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008201 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8202 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008203 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008204 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8205 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008206 mDispatcher->onWindowInfosChanged(
8207 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008208
8209 touch();
8210
8211 mTouchWindow->assertNoEvents();
8212}
8213
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008214TEST_F(InputDispatcherUntrustedTouchesTest,
8215 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8216 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008217 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8218 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008219 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008220 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8221 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008222 mDispatcher->onWindowInfosChanged(
8223 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008224
8225 touch();
8226
8227 mTouchWindow->assertNoEvents();
8228}
8229
8230TEST_F(InputDispatcherUntrustedTouchesTest,
8231 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8232 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008233 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8234 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008235 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008236 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8237 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008238 mDispatcher->onWindowInfosChanged(
8239 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008240
8241 touch();
8242
8243 mTouchWindow->consumeAnyMotionDown();
8244}
8245
8246TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8247 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008248 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8249 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008250 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008251
8252 touch();
8253
8254 mTouchWindow->consumeAnyMotionDown();
8255}
8256
8257TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8258 const sp<FakeWindowHandle>& w =
8259 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008260 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008261
8262 touch();
8263
8264 mTouchWindow->consumeAnyMotionDown();
8265}
8266
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008267TEST_F(InputDispatcherUntrustedTouchesTest,
8268 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8269 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8270 const sp<FakeWindowHandle>& w =
8271 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008272 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008273
8274 touch();
8275
8276 mTouchWindow->assertNoEvents();
8277}
8278
8279TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8280 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8281 const sp<FakeWindowHandle>& w =
8282 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008283 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008284
8285 touch();
8286
8287 mTouchWindow->consumeAnyMotionDown();
8288}
8289
8290TEST_F(InputDispatcherUntrustedTouchesTest,
8291 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8292 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8293 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008294 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8295 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008296 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008297
8298 touch();
8299
8300 mTouchWindow->consumeAnyMotionDown();
8301}
8302
8303TEST_F(InputDispatcherUntrustedTouchesTest,
8304 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8305 const sp<FakeWindowHandle>& w1 =
8306 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8307 OPACITY_BELOW_THRESHOLD);
8308 const sp<FakeWindowHandle>& w2 =
8309 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8310 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008311 mDispatcher->onWindowInfosChanged(
8312 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008313
8314 touch();
8315
8316 mTouchWindow->assertNoEvents();
8317}
8318
8319/**
8320 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8321 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8322 * (which alone would result in allowing touches) does not affect the blocking behavior.
8323 */
8324TEST_F(InputDispatcherUntrustedTouchesTest,
8325 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8326 const sp<FakeWindowHandle>& wB =
8327 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8328 OPACITY_BELOW_THRESHOLD);
8329 const sp<FakeWindowHandle>& wC =
8330 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8331 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008332 mDispatcher->onWindowInfosChanged(
8333 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008334
8335 touch();
8336
8337 mTouchWindow->assertNoEvents();
8338}
8339
8340/**
8341 * This test is testing that a window from a different UID but with same application token doesn't
8342 * block the touch. Apps can share the application token for close UI collaboration for example.
8343 */
8344TEST_F(InputDispatcherUntrustedTouchesTest,
8345 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8346 const sp<FakeWindowHandle>& w =
8347 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8348 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008349 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008350
8351 touch();
8352
8353 mTouchWindow->consumeAnyMotionDown();
8354}
8355
arthurhungb89ccb02020-12-30 16:19:01 +08008356class InputDispatcherDragTests : public InputDispatcherTest {
8357protected:
8358 std::shared_ptr<FakeApplicationHandle> mApp;
8359 sp<FakeWindowHandle> mWindow;
8360 sp<FakeWindowHandle> mSecondWindow;
8361 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008362 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008363 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8364 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008365
8366 void SetUp() override {
8367 InputDispatcherTest::SetUp();
8368 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008369 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008370 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008371
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008372 mSecondWindow =
8373 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008374 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008375
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008376 mSpyWindow =
8377 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008378 mSpyWindow->setSpy(true);
8379 mSpyWindow->setTrustedOverlay(true);
8380 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8381
arthurhungb89ccb02020-12-30 16:19:01 +08008382 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008383 mDispatcher->onWindowInfosChanged(
8384 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8385 {},
8386 0,
8387 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008388 }
8389
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008390 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8391 switch (fromSource) {
8392 case AINPUT_SOURCE_TOUCHSCREEN:
8393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008394 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008395 ADISPLAY_ID_DEFAULT, {50, 50}))
8396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8397 break;
8398 case AINPUT_SOURCE_STYLUS:
8399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008400 injectMotionEvent(*mDispatcher,
8401 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8402 AINPUT_SOURCE_STYLUS)
8403 .buttonState(
8404 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8405 .pointer(PointerBuilder(0, ToolType::STYLUS)
8406 .x(50)
8407 .y(50))
8408 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008409 break;
8410 case AINPUT_SOURCE_MOUSE:
8411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008412 injectMotionEvent(*mDispatcher,
8413 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8414 AINPUT_SOURCE_MOUSE)
8415 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8416 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8417 ToolType::MOUSE)
8418 .x(50)
8419 .y(50))
8420 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008421 break;
8422 default:
8423 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8424 }
arthurhungb89ccb02020-12-30 16:19:01 +08008425
8426 // Window should receive motion event.
8427 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008428 // Spy window should also receive motion event
8429 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008430 }
8431
8432 // Start performing drag, we will create a drag window and transfer touch to it.
8433 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8434 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008435 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008436 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008437 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008438 }
arthurhungb89ccb02020-12-30 16:19:01 +08008439
8440 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008441 mDragWindow =
8442 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008443 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008444 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8445 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8446 {},
8447 0,
8448 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008449
8450 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008451 bool transferred =
8452 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008453 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008454 if (transferred) {
8455 mWindow->consumeMotionCancel();
8456 mDragWindow->consumeMotionDown();
8457 }
8458 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008459 }
8460};
8461
8462TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008463 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008464
8465 // Move on window.
8466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008467 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008468 ADISPLAY_ID_DEFAULT, {50, 50}))
8469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8470 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8471 mWindow->consumeDragEvent(false, 50, 50);
8472 mSecondWindow->assertNoEvents();
8473
8474 // Move to another window.
8475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008476 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008477 ADISPLAY_ID_DEFAULT, {150, 50}))
8478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8479 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8480 mWindow->consumeDragEvent(true, 150, 50);
8481 mSecondWindow->consumeDragEvent(false, 50, 50);
8482
8483 // Move back to original window.
8484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008485 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008486 ADISPLAY_ID_DEFAULT, {50, 50}))
8487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8488 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8489 mWindow->consumeDragEvent(false, 50, 50);
8490 mSecondWindow->consumeDragEvent(true, -50, 50);
8491
8492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008493 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8494 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08008495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8496 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8497 mWindow->assertNoEvents();
8498 mSecondWindow->assertNoEvents();
8499}
8500
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008501TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008502 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008503
8504 // No cancel event after drag start
8505 mSpyWindow->assertNoEvents();
8506
8507 const MotionEvent secondFingerDownEvent =
8508 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8509 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008510 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8511 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008512 .build();
8513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008514 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008515 InputEventInjectionSync::WAIT_FOR_RESULT))
8516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8517
8518 // Receives cancel for first pointer after next pointer down
8519 mSpyWindow->consumeMotionCancel();
8520 mSpyWindow->consumeMotionDown();
8521
8522 mSpyWindow->assertNoEvents();
8523}
8524
arthurhungf452d0b2021-01-06 00:19:52 +08008525TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008526 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008527
8528 // Move on window.
8529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008530 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08008531 ADISPLAY_ID_DEFAULT, {50, 50}))
8532 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8533 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8534 mWindow->consumeDragEvent(false, 50, 50);
8535 mSecondWindow->assertNoEvents();
8536
8537 // Move to another window.
8538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008539 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08008540 ADISPLAY_ID_DEFAULT, {150, 50}))
8541 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8542 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8543 mWindow->consumeDragEvent(true, 150, 50);
8544 mSecondWindow->consumeDragEvent(false, 50, 50);
8545
8546 // drop to another window.
8547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008548 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08008549 {150, 50}))
8550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8551 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008552 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008553 mWindow->assertNoEvents();
8554 mSecondWindow->assertNoEvents();
8555}
8556
arthurhung6d4bed92021-03-17 11:59:33 +08008557TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008558 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008559
8560 // Move on window and keep button pressed.
8561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008562 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008563 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8564 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008566 .build()))
8567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8568 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8569 mWindow->consumeDragEvent(false, 50, 50);
8570 mSecondWindow->assertNoEvents();
8571
8572 // Move to another window and release button, expect to drop item.
8573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008574 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008575 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8576 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008577 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008578 .build()))
8579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8580 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8581 mWindow->assertNoEvents();
8582 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008583 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008584
8585 // nothing to the window.
8586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008587 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008588 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8589 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008591 .build()))
8592 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8593 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8594 mWindow->assertNoEvents();
8595 mSecondWindow->assertNoEvents();
8596}
8597
Arthur Hung54745652022-04-20 07:17:41 +00008598TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008599 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008600
8601 // Set second window invisible.
8602 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008603 mDispatcher->onWindowInfosChanged(
8604 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08008605
8606 // Move on window.
8607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008608 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008609 ADISPLAY_ID_DEFAULT, {50, 50}))
8610 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8611 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8612 mWindow->consumeDragEvent(false, 50, 50);
8613 mSecondWindow->assertNoEvents();
8614
8615 // Move to another window.
8616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008617 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008618 ADISPLAY_ID_DEFAULT, {150, 50}))
8619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8620 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8621 mWindow->consumeDragEvent(true, 150, 50);
8622 mSecondWindow->assertNoEvents();
8623
8624 // drop to another window.
8625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008626 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008627 {150, 50}))
8628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8629 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008630 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008631 mWindow->assertNoEvents();
8632 mSecondWindow->assertNoEvents();
8633}
8634
Arthur Hung54745652022-04-20 07:17:41 +00008635TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008636 // Ensure window could track pointerIds if it didn't support split touch.
8637 mWindow->setPreventSplitting(true);
8638
Arthur Hung54745652022-04-20 07:17:41 +00008639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008640 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00008641 {50, 50}))
8642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8643 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8644
8645 const MotionEvent secondFingerDownEvent =
8646 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8647 .displayId(ADISPLAY_ID_DEFAULT)
8648 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008649 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8650 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008651 .build();
8652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008653 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008654 InputEventInjectionSync::WAIT_FOR_RESULT))
8655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008656 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008657
8658 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008659 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008660}
8661
8662TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8663 // First down on second window.
8664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00008666 {150, 50}))
8667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8668
8669 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8670
8671 // Second down on first window.
8672 const MotionEvent secondFingerDownEvent =
8673 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8674 .displayId(ADISPLAY_ID_DEFAULT)
8675 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008676 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8677 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008678 .build();
8679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008680 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008681 InputEventInjectionSync::WAIT_FOR_RESULT))
8682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8683 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8684
8685 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008686 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008687
8688 // Move on window.
8689 const MotionEvent secondFingerMoveEvent =
8690 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8691 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008692 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8693 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008694 .build();
8695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008696 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008697 InputEventInjectionSync::WAIT_FOR_RESULT));
8698 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8699 mWindow->consumeDragEvent(false, 50, 50);
8700 mSecondWindow->consumeMotionMove();
8701
8702 // Release the drag pointer should perform drop.
8703 const MotionEvent secondFingerUpEvent =
8704 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8705 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008706 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8707 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008708 .build();
8709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008710 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008711 InputEventInjectionSync::WAIT_FOR_RESULT));
8712 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008713 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008714 mWindow->assertNoEvents();
8715 mSecondWindow->consumeMotionMove();
8716}
8717
Arthur Hung3915c1f2022-05-31 07:17:17 +00008718TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008719 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008720
8721 // Update window of second display.
8722 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008723 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008724 mDispatcher->onWindowInfosChanged(
8725 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8726 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8727 {},
8728 0,
8729 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008730
8731 // Let second display has a touch state.
8732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008733 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008734 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8735 AINPUT_SOURCE_TOUCHSCREEN)
8736 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008737 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008738 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008739 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008740 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008741 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008742 mDispatcher->onWindowInfosChanged(
8743 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8744 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8745 {},
8746 0,
8747 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008748
8749 // Move on window.
8750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008751 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008752 ADISPLAY_ID_DEFAULT, {50, 50}))
8753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8754 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8755 mWindow->consumeDragEvent(false, 50, 50);
8756 mSecondWindow->assertNoEvents();
8757
8758 // Move to another window.
8759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008760 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008761 ADISPLAY_ID_DEFAULT, {150, 50}))
8762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8763 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8764 mWindow->consumeDragEvent(true, 150, 50);
8765 mSecondWindow->consumeDragEvent(false, 50, 50);
8766
8767 // drop to another window.
8768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008769 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008770 {150, 50}))
8771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8772 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008773 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008774 mWindow->assertNoEvents();
8775 mSecondWindow->assertNoEvents();
8776}
8777
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008778TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8779 startDrag(true, AINPUT_SOURCE_MOUSE);
8780 // Move on window.
8781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008782 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008783 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8784 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008785 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008786 .x(50)
8787 .y(50))
8788 .build()))
8789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8790 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8791 mWindow->consumeDragEvent(false, 50, 50);
8792 mSecondWindow->assertNoEvents();
8793
8794 // Move to another window.
8795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008796 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008797 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8798 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008799 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008800 .x(150)
8801 .y(50))
8802 .build()))
8803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8804 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8805 mWindow->consumeDragEvent(true, 150, 50);
8806 mSecondWindow->consumeDragEvent(false, 50, 50);
8807
8808 // drop to another window.
8809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008810 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008811 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8812 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008813 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008814 .x(150)
8815 .y(50))
8816 .build()))
8817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8818 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008819 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008820 mWindow->assertNoEvents();
8821 mSecondWindow->assertNoEvents();
8822}
8823
Vishnu Nair062a8672021-09-03 16:07:44 -07008824class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8825
8826TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008828 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8829 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008830 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008831 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8832 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008833 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008834 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008835 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008836
8837 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008838 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008839 window->assertNoEvents();
8840
Prabir Pradhan678438e2023-04-13 19:32:51 +00008841 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8842 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008843 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8844 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008845 window->assertNoEvents();
8846
8847 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008848 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008849 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008850
Prabir Pradhan678438e2023-04-13 19:32:51 +00008851 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008852 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8853
Prabir Pradhan678438e2023-04-13 19:32:51 +00008854 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8855 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008856 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8857 window->assertNoEvents();
8858}
8859
8860TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8861 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8862 std::make_shared<FakeApplicationHandle>();
8863 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008864 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8865 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008866 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008867 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008868 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008869 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008870 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8871 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008872 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008873 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008874 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8875 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008876 mDispatcher->onWindowInfosChanged(
8877 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008878 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008879 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008880
8881 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008882 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008883 window->assertNoEvents();
8884
Prabir Pradhan678438e2023-04-13 19:32:51 +00008885 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8886 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008887 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8888 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008889 window->assertNoEvents();
8890
8891 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008892 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008893 mDispatcher->onWindowInfosChanged(
8894 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008895
Prabir Pradhan678438e2023-04-13 19:32:51 +00008896 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008897 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8898
Prabir Pradhan678438e2023-04-13 19:32:51 +00008899 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8900 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008901 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8902 window->assertNoEvents();
8903}
8904
8905TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8906 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8907 std::make_shared<FakeApplicationHandle>();
8908 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008909 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8910 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008911 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008912 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008913 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008915 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8916 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008917 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008918 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008919 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8920 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008921 mDispatcher->onWindowInfosChanged(
8922 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008923 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008924 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008925
8926 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008927 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008928 window->assertNoEvents();
8929
Prabir Pradhan678438e2023-04-13 19:32:51 +00008930 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8931 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008932 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8933 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008934 window->assertNoEvents();
8935
8936 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008937 mDispatcher->onWindowInfosChanged(
8938 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008939
Prabir Pradhan678438e2023-04-13 19:32:51 +00008940 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008941 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8942
Prabir Pradhan678438e2023-04-13 19:32:51 +00008943 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8944 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008945 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8946 window->assertNoEvents();
8947}
8948
Antonio Kantekf16f2832021-09-28 04:39:20 +00008949class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8950protected:
8951 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008952 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008953 sp<FakeWindowHandle> mWindow;
8954 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008955 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008956
8957 void SetUp() override {
8958 InputDispatcherTest::SetUp();
8959
8960 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008961 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008962 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008963 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008964 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008965 mSecondWindow =
8966 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008967 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008968 mThirdWindow =
8969 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8970 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8971 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008972
8973 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008974 mDispatcher->onWindowInfosChanged(
8975 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
8976 {},
8977 0,
8978 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00008979 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008980 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008981
Antonio Kantek15beb512022-06-13 22:35:41 +00008982 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008983 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008984 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008985 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8986 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008987 mThirdWindow->assertNoEvents();
8988 }
8989
8990 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8991 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008992 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008993 SECOND_DISPLAY_ID)) {
8994 mWindow->assertNoEvents();
8995 mSecondWindow->assertNoEvents();
8996 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008997 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008998 }
8999
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009000 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009001 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009002 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9003 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009004 mWindow->consumeTouchModeEvent(inTouchMode);
9005 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009006 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009007 }
9008};
9009
Antonio Kantek26defcf2022-02-08 01:12:27 +00009010TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009011 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009012 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9013 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009014 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009015}
9016
Antonio Kantek26defcf2022-02-08 01:12:27 +00009017TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9018 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009019 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009020 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009021 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009022 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009023 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009024 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009025 mWindow->assertNoEvents();
9026 mSecondWindow->assertNoEvents();
9027}
9028
9029TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9030 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009031 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009032 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009033 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009034 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009035 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009036}
9037
Antonio Kantekf16f2832021-09-28 04:39:20 +00009038TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009039 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009040 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9041 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009042 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009043 mWindow->assertNoEvents();
9044 mSecondWindow->assertNoEvents();
9045}
9046
Antonio Kantek15beb512022-06-13 22:35:41 +00009047TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9048 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9049 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9050 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009051 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009052 mWindow->assertNoEvents();
9053 mSecondWindow->assertNoEvents();
9054 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9055}
9056
Antonio Kantek48710e42022-03-24 14:19:30 -07009057TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9058 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9060 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009061 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9062 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9063
9064 // Then remove focus.
9065 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009066 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009067
9068 // Assert that caller can switch touch mode by owning one of the last interacted window.
9069 const WindowInfo& windowInfo = *mWindow->getInfo();
9070 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9071 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009072 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009073}
9074
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009075class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9076public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009077 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009078 std::shared_ptr<FakeApplicationHandle> application =
9079 std::make_shared<FakeApplicationHandle>();
9080 std::string name = "Fake Spy ";
9081 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009082 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9083 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009084 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009085 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009086 return spy;
9087 }
9088
9089 sp<FakeWindowHandle> createForeground() {
9090 std::shared_ptr<FakeApplicationHandle> application =
9091 std::make_shared<FakeApplicationHandle>();
9092 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009093 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9094 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009095 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009096 return window;
9097 }
9098
9099private:
9100 int mSpyCount{0};
9101};
9102
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009103using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009104/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009105 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9106 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009107TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009108 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009109 ScopedSilentDeath _silentDeath;
9110
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009111 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009112 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009113 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009114 ".* not a trusted overlay");
9115}
9116
9117/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009118 * Input injection into a display with a spy window but no foreground windows should succeed.
9119 */
9120TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009121 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009122 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009123
9124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009125 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9127 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9128}
9129
9130/**
9131 * Verify the order in which different input windows receive events. The touched foreground window
9132 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9133 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9134 * receive events before ones belows it.
9135 *
9136 * Here, we set up a scenario with four windows in the following Z order from the top:
9137 * spy1, spy2, window, spy3.
9138 * We then inject an event and verify that the foreground "window" receives it first, followed by
9139 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9140 * window.
9141 */
9142TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9143 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009144 auto spy1 = createSpy();
9145 auto spy2 = createSpy();
9146 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009147 mDispatcher->onWindowInfosChanged(
9148 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009149 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9150 const size_t numChannels = channels.size();
9151
Michael Wright8e9a8562022-02-09 13:44:29 +00009152 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009153 if (!epollFd.ok()) {
9154 FAIL() << "Failed to create epoll fd";
9155 }
9156
9157 for (size_t i = 0; i < numChannels; i++) {
9158 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9159 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9160 FAIL() << "Failed to add fd to epoll";
9161 }
9162 }
9163
9164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009165 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9167
9168 std::vector<size_t> eventOrder;
9169 std::vector<struct epoll_event> events(numChannels);
9170 for (;;) {
9171 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9172 (100ms).count());
9173 if (nFds < 0) {
9174 FAIL() << "Failed to call epoll_wait";
9175 }
9176 if (nFds == 0) {
9177 break; // epoll_wait timed out
9178 }
9179 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009180 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009181 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009182 channels[i]->consumeMotionDown();
9183 }
9184 }
9185
9186 // Verify the order in which the events were received.
9187 EXPECT_EQ(3u, eventOrder.size());
9188 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9189 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9190 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9191}
9192
9193/**
9194 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9195 */
9196TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9197 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009198 auto spy = createSpy();
9199 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009200 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009201
9202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009203 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9205 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9206 spy->assertNoEvents();
9207}
9208
9209/**
9210 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9211 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9212 * to the window.
9213 */
9214TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9215 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009216 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009217 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009218 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009219
9220 // Inject an event outside the spy window's touchable region.
9221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009222 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009223 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9224 window->consumeMotionDown();
9225 spy->assertNoEvents();
9226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009227 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9229 window->consumeMotionUp();
9230 spy->assertNoEvents();
9231
9232 // Inject an event inside the spy window's touchable region.
9233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009234 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009235 {5, 10}))
9236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9237 window->consumeMotionDown();
9238 spy->consumeMotionDown();
9239}
9240
9241/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009242 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009243 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009244 */
9245TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9246 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009247 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009248 auto spy = createSpy();
9249 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009250 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009251 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009252 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009253
9254 // Inject an event outside the spy window's frame and touchable region.
9255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009256 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009257 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009258 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9259 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009260 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009261}
9262
9263/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009264 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9265 * pointers that are down within its bounds.
9266 */
9267TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9268 auto windowLeft = createForeground();
9269 windowLeft->setFrame({0, 0, 100, 200});
9270 auto windowRight = createForeground();
9271 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009272 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009273 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009274 mDispatcher->onWindowInfosChanged(
9275 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009276
9277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009278 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009279 {50, 50}))
9280 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9281 windowLeft->consumeMotionDown();
9282 spy->consumeMotionDown();
9283
9284 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009285 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009286 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009287 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9288 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009289 .build();
9290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009291 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009292 InputEventInjectionSync::WAIT_FOR_RESULT))
9293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9294 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009295 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009296}
9297
9298/**
9299 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9300 * the spy should receive the second pointer with ACTION_DOWN.
9301 */
9302TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9303 auto window = createForeground();
9304 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009305 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009306 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009307 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009308
9309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009310 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009311 {50, 50}))
9312 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9313 window->consumeMotionDown();
9314 spyRight->assertNoEvents();
9315
9316 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009317 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009318 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009319 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9320 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009321 .build();
9322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009323 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009324 InputEventInjectionSync::WAIT_FOR_RESULT))
9325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009326 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009327 spyRight->consumeMotionDown();
9328}
9329
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009330/**
9331 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9332 * windows should be allowed to control split touch.
9333 */
9334TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009335 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009336 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009337 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009338 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009339
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009340 auto window = createForeground();
9341 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009342
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009343 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009344
9345 // First finger down, no window touched.
9346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009347 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009348 {100, 200}))
9349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9350 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9351 window->assertNoEvents();
9352
9353 // Second finger down on window, the window should receive touch down.
9354 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009355 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009356 .displayId(ADISPLAY_ID_DEFAULT)
9357 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009358 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9359 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009360 .build();
9361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009362 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009363 InputEventInjectionSync::WAIT_FOR_RESULT))
9364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9365
9366 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009367 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009368}
9369
9370/**
9371 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9372 * do not receive key events.
9373 */
9374TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009375 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009376 spy->setFocusable(false);
9377
9378 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009379 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009380 setFocusedWindow(window);
9381 window->consumeFocusEvent(true);
9382
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009384 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9385 window->consumeKeyDown(ADISPLAY_ID_NONE);
9386
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009388 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9389 window->consumeKeyUp(ADISPLAY_ID_NONE);
9390
9391 spy->assertNoEvents();
9392}
9393
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009394using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9395
9396/**
9397 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9398 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9399 */
9400TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9401 auto window = createForeground();
9402 auto spy1 = createSpy();
9403 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009404 mDispatcher->onWindowInfosChanged(
9405 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009406
9407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009408 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009409 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9410 window->consumeMotionDown();
9411 spy1->consumeMotionDown();
9412 spy2->consumeMotionDown();
9413
9414 // Pilfer pointers from the second spy window.
9415 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9416 spy2->assertNoEvents();
9417 spy1->consumeMotionCancel();
9418 window->consumeMotionCancel();
9419
9420 // The rest of the gesture should only be sent to the second spy window.
9421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009422 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009423 ADISPLAY_ID_DEFAULT))
9424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9425 spy2->consumeMotionMove();
9426 spy1->assertNoEvents();
9427 window->assertNoEvents();
9428}
9429
9430/**
9431 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9432 * in the middle of the gesture.
9433 */
9434TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9435 auto window = createForeground();
9436 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009437 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009438
9439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009440 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9442 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9443 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9444
9445 window->releaseChannel();
9446
9447 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9448
9449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009450 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9452 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9453}
9454
9455/**
9456 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9457 * the spy, but not to any other windows.
9458 */
9459TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9460 auto spy = createSpy();
9461 auto window = createForeground();
9462
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009463 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009464
9465 // First finger down on the window and the spy.
9466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009468 {100, 200}))
9469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9470 spy->consumeMotionDown();
9471 window->consumeMotionDown();
9472
9473 // Spy window pilfers the pointers.
9474 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9475 window->consumeMotionCancel();
9476
9477 // Second finger down on the window and spy, but the window should not receive the pointer down.
9478 const MotionEvent secondFingerDownEvent =
9479 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9480 .displayId(ADISPLAY_ID_DEFAULT)
9481 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009482 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9483 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009484 .build();
9485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009486 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009487 InputEventInjectionSync::WAIT_FOR_RESULT))
9488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9489
Harry Cutts33476232023-01-30 19:57:29 +00009490 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009491
9492 // Third finger goes down outside all windows, so injection should fail.
9493 const MotionEvent thirdFingerDownEvent =
9494 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9495 .displayId(ADISPLAY_ID_DEFAULT)
9496 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009497 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9498 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9499 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009500 .build();
9501 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009502 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009503 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009504 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009505
9506 spy->assertNoEvents();
9507 window->assertNoEvents();
9508}
9509
9510/**
9511 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9512 */
9513TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9514 auto spy = createSpy();
9515 spy->setFrame(Rect(0, 0, 100, 100));
9516 auto window = createForeground();
9517 window->setFrame(Rect(0, 0, 200, 200));
9518
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009519 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009520
9521 // First finger down on the window only
9522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009523 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009524 {150, 150}))
9525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9526 window->consumeMotionDown();
9527
9528 // Second finger down on the spy and window
9529 const MotionEvent secondFingerDownEvent =
9530 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9531 .displayId(ADISPLAY_ID_DEFAULT)
9532 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009533 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9534 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009535 .build();
9536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009537 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009538 InputEventInjectionSync::WAIT_FOR_RESULT))
9539 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9540 spy->consumeMotionDown();
9541 window->consumeMotionPointerDown(1);
9542
9543 // Third finger down on the spy and window
9544 const MotionEvent thirdFingerDownEvent =
9545 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9546 .displayId(ADISPLAY_ID_DEFAULT)
9547 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009548 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9549 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9550 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009551 .build();
9552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009553 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009554 InputEventInjectionSync::WAIT_FOR_RESULT))
9555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9556 spy->consumeMotionPointerDown(1);
9557 window->consumeMotionPointerDown(2);
9558
9559 // Spy window pilfers the pointers.
9560 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009561 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9562 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009563
9564 spy->assertNoEvents();
9565 window->assertNoEvents();
9566}
9567
9568/**
9569 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9570 * other windows should be canceled. If this results in the cancellation of all pointers for some
9571 * window, then that window should receive ACTION_CANCEL.
9572 */
9573TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9574 auto spy = createSpy();
9575 spy->setFrame(Rect(0, 0, 100, 100));
9576 auto window = createForeground();
9577 window->setFrame(Rect(0, 0, 200, 200));
9578
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009579 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009580
9581 // First finger down on both spy and window
9582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009583 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009584 {10, 10}))
9585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9586 window->consumeMotionDown();
9587 spy->consumeMotionDown();
9588
9589 // Second finger down on the spy and window
9590 const MotionEvent secondFingerDownEvent =
9591 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9592 .displayId(ADISPLAY_ID_DEFAULT)
9593 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009594 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9595 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009596 .build();
9597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009598 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009599 InputEventInjectionSync::WAIT_FOR_RESULT))
9600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9601 spy->consumeMotionPointerDown(1);
9602 window->consumeMotionPointerDown(1);
9603
9604 // Spy window pilfers the pointers.
9605 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9606 window->consumeMotionCancel();
9607
9608 spy->assertNoEvents();
9609 window->assertNoEvents();
9610}
9611
9612/**
9613 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9614 * be sent to other windows
9615 */
9616TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9617 auto spy = createSpy();
9618 spy->setFrame(Rect(0, 0, 100, 100));
9619 auto window = createForeground();
9620 window->setFrame(Rect(0, 0, 200, 200));
9621
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009622 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009623
9624 // First finger down on both window and spy
9625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009626 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009627 {10, 10}))
9628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9629 window->consumeMotionDown();
9630 spy->consumeMotionDown();
9631
9632 // Spy window pilfers the pointers.
9633 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9634 window->consumeMotionCancel();
9635
9636 // Second finger down on the window only
9637 const MotionEvent secondFingerDownEvent =
9638 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9639 .displayId(ADISPLAY_ID_DEFAULT)
9640 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009641 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9642 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009643 .build();
9644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009645 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009646 InputEventInjectionSync::WAIT_FOR_RESULT))
9647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9648 window->consumeMotionDown();
9649 window->assertNoEvents();
9650
9651 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9652 spy->consumeMotionMove();
9653 spy->assertNoEvents();
9654}
9655
Prabir Pradhand65552b2021-10-07 11:23:50 -07009656class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9657public:
9658 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9659 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9660 std::make_shared<FakeApplicationHandle>();
9661 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009662 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9663 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009664 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009665 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009666 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009667 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009668 overlay->setTrustedOverlay(true);
9669
9670 std::shared_ptr<FakeApplicationHandle> application =
9671 std::make_shared<FakeApplicationHandle>();
9672 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009673 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9674 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009675 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009676 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009677
9678 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009679 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009680 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009681 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009682 return {std::move(overlay), std::move(window)};
9683 }
9684
9685 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009686 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009687 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009688 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009689 }
9690
9691 void sendStylusEvent(int32_t action) {
9692 NotifyMotionArgs motionArgs =
9693 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9694 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009695 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009696 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009697 }
9698};
9699
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009700using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9701
9702TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009703 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009704 ScopedSilentDeath _silentDeath;
9705
Prabir Pradhand65552b2021-10-07 11:23:50 -07009706 auto [overlay, window] = setupStylusOverlayScenario();
9707 overlay->setTrustedOverlay(false);
9708 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009709 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
9710 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -07009711 ".* not a trusted overlay");
9712}
9713
9714TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9715 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009716 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009717
9718 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9719 overlay->consumeMotionDown();
9720 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9721 overlay->consumeMotionUp();
9722
9723 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9724 window->consumeMotionDown();
9725 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9726 window->consumeMotionUp();
9727
9728 overlay->assertNoEvents();
9729 window->assertNoEvents();
9730}
9731
9732TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9733 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009734 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009735 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009736
9737 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9738 overlay->consumeMotionDown();
9739 window->consumeMotionDown();
9740 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9741 overlay->consumeMotionUp();
9742 window->consumeMotionUp();
9743
9744 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9745 window->consumeMotionDown();
9746 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9747 window->consumeMotionUp();
9748
9749 overlay->assertNoEvents();
9750 window->assertNoEvents();
9751}
9752
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009753/**
9754 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9755 * The scenario is as follows:
9756 * - The stylus interceptor overlay is configured as a spy window.
9757 * - The stylus interceptor spy receives the start of a new stylus gesture.
9758 * - It pilfers pointers and then configures itself to no longer be a spy.
9759 * - The stylus interceptor continues to receive the rest of the gesture.
9760 */
9761TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9762 auto [overlay, window] = setupStylusOverlayScenario();
9763 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009764 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009765
9766 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9767 overlay->consumeMotionDown();
9768 window->consumeMotionDown();
9769
9770 // The interceptor pilfers the pointers.
9771 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9772 window->consumeMotionCancel();
9773
9774 // The interceptor configures itself so that it is no longer a spy.
9775 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009776 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009777
9778 // It continues to receive the rest of the stylus gesture.
9779 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9780 overlay->consumeMotionMove();
9781 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9782 overlay->consumeMotionUp();
9783
9784 window->assertNoEvents();
9785}
9786
Prabir Pradhan5735a322022-04-11 17:23:34 +00009787struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009788 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009789 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009790 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9791 std::unique_ptr<InputDispatcher>& mDispatcher;
9792
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009793 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009794 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9795
9796 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009797 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009798 ADISPLAY_ID_DEFAULT, {100, 200},
9799 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9800 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9801 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9802 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9803 }
9804
9805 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009806 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009807 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009808 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009809 mPolicyFlags);
9810 }
9811
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009812 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +00009813 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9814 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009815 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9816 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009817 window->setOwnerInfo(mPid, mUid);
9818 return window;
9819 }
9820};
9821
9822using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9823
9824TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009825 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009826 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009827 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009828
9829 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9830 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9831 window->consumeMotionDown();
9832
9833 setFocusedWindow(window);
9834 window->consumeFocusEvent(true);
9835
9836 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9837 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9838 window->consumeKeyDown(ADISPLAY_ID_NONE);
9839}
9840
9841TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009842 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009843 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009844 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009845
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009846 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009847 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9848 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9849
9850 setFocusedWindow(window);
9851 window->consumeFocusEvent(true);
9852
9853 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9854 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9855 window->assertNoEvents();
9856}
9857
9858TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009859 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009860 auto window = owner.createWindow("Owned window");
9861 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009862 spy->setSpy(true);
9863 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009864 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009865
9866 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9867 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9868 spy->consumeMotionDown();
9869 window->consumeMotionDown();
9870}
9871
9872TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009873 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009874 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009875
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009876 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009877 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009878 randosSpy->setSpy(true);
9879 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009880 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009881
9882 // The event is targeted at owner's window, so injection should succeed, but the spy should
9883 // not receive the event.
9884 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9885 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9886 randosSpy->assertNoEvents();
9887 window->consumeMotionDown();
9888}
9889
9890TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009891 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009892 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009893
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009894 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009895 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009896 randosSpy->setSpy(true);
9897 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009898 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009899
9900 // A user that has injection permission can inject into any window.
9901 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009902 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009903 ADISPLAY_ID_DEFAULT));
9904 randosSpy->consumeMotionDown();
9905 window->consumeMotionDown();
9906
9907 setFocusedWindow(randosSpy);
9908 randosSpy->consumeFocusEvent(true);
9909
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009910 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +00009911 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9912 window->assertNoEvents();
9913}
9914
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009915TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009916 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009917 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009918
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009919 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009920 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009921 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9922 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009923 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009924
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009925 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009926 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9927 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9928 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009929 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009930}
9931
Garfield Tane84e6f92019-08-29 17:28:41 -07009932} // namespace android::inputdispatcher