blob: 6d9cd87c4f221096c07f46cb4cc15bdb7e61b114 [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;
chaviwd1c23182019-12-20 18:44:56 -08001134 mInfo.frameLeft = 0;
1135 mInfo.frameTop = 0;
1136 mInfo.frameRight = WIDTH;
1137 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001138 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001139 mInfo.globalScaleFactor = 1.0;
1140 mInfo.touchableRegion.clear();
1141 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001142 mInfo.ownerPid = WINDOW_PID;
1143 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001144 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001145 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001146 }
1147
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001148 sp<FakeWindowHandle> clone(int32_t displayId) {
1149 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1150 handle->mInfo = mInfo;
1151 handle->mInfo.displayId = displayId;
1152 handle->mInfo.id = sId++;
1153 handle->mInputReceiver = mInputReceiver;
1154 return handle;
1155 }
1156
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001157 void setTouchable(bool touchable) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1159 }
chaviwd1c23182019-12-20 18:44:56 -08001160
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001161 void setFocusable(bool focusable) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1163 }
1164
1165 void setVisible(bool visible) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1167 }
Vishnu Nair958da932020-08-21 17:12:37 -07001168
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001169 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001170 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001171 }
1172
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001173 void setPaused(bool paused) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1175 }
1176
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001177 void setPreventSplitting(bool preventSplitting) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001179 }
1180
1181 void setSlippery(bool slippery) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1183 }
1184
1185 void setWatchOutsideTouch(bool watchOutside) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1187 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001188
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001189 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1190
1191 void setInterceptsStylus(bool interceptsStylus) {
1192 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1193 }
1194
1195 void setDropInput(bool dropInput) {
1196 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1197 }
1198
1199 void setDropInputIfObscured(bool dropInputIfObscured) {
1200 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1201 }
1202
1203 void setNoInputChannel(bool noInputChannel) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1205 }
1206
Josep del Riob3981622023-04-18 15:49:45 +00001207 void setDisableUserActivity(bool disableUserActivity) {
1208 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1209 }
1210
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001211 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1212
chaviw3277faf2021-05-19 16:45:23 -05001213 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001214
Bernardo Rufino7393d172021-02-26 13:56:11 +00001215 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1216
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001217 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001218 mInfo.frameLeft = frame.left;
1219 mInfo.frameTop = frame.top;
1220 mInfo.frameRight = frame.right;
1221 mInfo.frameBottom = frame.bottom;
1222 mInfo.touchableRegion.clear();
1223 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001224
1225 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1226 ui::Transform translate;
1227 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1228 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001229 }
1230
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001231 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1232
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001233 void setIsWallpaper(bool isWallpaper) {
1234 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1235 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001236
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001237 void setDupTouchToWallpaper(bool hasWallpaper) {
1238 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1239 }
chaviwd1c23182019-12-20 18:44:56 -08001240
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001241 void setTrustedOverlay(bool trustedOverlay) {
1242 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1243 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001244
chaviw9eaa22c2020-07-01 16:21:27 -07001245 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1246 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1247 }
1248
1249 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001250
yunho.shinf4a80b82020-11-16 21:13:57 +09001251 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1252
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001253 KeyEvent* consumeKey() {
1254 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1255 if (event == nullptr) {
1256 ADD_FAILURE() << "Consume failed : no event";
1257 return nullptr;
1258 }
1259 if (event->getType() != InputEventType::KEY) {
1260 ADD_FAILURE() << "Instead of key event, got " << *event;
1261 return nullptr;
1262 }
1263 return static_cast<KeyEvent*>(event);
1264 }
1265
1266 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1267 KeyEvent* keyEvent = consumeKey();
1268 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1269 ASSERT_THAT(*keyEvent, matcher);
1270 }
1271
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001272 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001273 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001274 }
1275
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001276 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001277 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001278 }
1279
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 void consumeMotionCancel(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(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1283 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001284 }
1285
1286 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001287 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001288 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1289 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001290 }
1291
1292 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001294 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1295 }
1296
1297 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1298 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001299 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001300 expectedFlags);
1301 }
1302
Svet Ganov5d3bc372020-01-26 23:11:07 -08001303 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001304 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1305 int32_t expectedFlags = 0) {
1306 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1307 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001308 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 }
1310
1311 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedFlags = 0) {
1313 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1314 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001315 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001316 }
1317
1318 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001319 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001320 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001321 expectedFlags);
1322 }
1323
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001324 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1325 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001327 expectedFlags);
1328 }
1329
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001330 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1331 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001332 MotionEvent* motionEvent = consumeMotion();
1333 ASSERT_NE(nullptr, motionEvent);
1334 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1335 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1336 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001337 }
1338
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001339 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1340 ASSERT_NE(mInputReceiver, nullptr)
1341 << "Cannot consume events from a window with no receiver";
1342 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1343 }
1344
Prabir Pradhan99987712020-11-10 18:43:05 -08001345 void consumeCaptureEvent(bool hasCapture) {
1346 ASSERT_NE(mInputReceiver, nullptr)
1347 << "Cannot consume events from a window with no receiver";
1348 mInputReceiver->consumeCaptureEvent(hasCapture);
1349 }
1350
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001351 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1352 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001353 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001354 ASSERT_THAT(*motionEvent, matcher);
1355 }
1356
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001357 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001358 std::optional<int32_t> expectedDisplayId,
1359 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001360 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1361 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1362 expectedFlags);
1363 }
1364
arthurhungb89ccb02020-12-30 16:19:01 +08001365 void consumeDragEvent(bool isExiting, float x, float y) {
1366 mInputReceiver->consumeDragEvent(isExiting, x, y);
1367 }
1368
Antonio Kantekf16f2832021-09-28 04:39:20 +00001369 void consumeTouchModeEvent(bool inTouchMode) {
1370 ASSERT_NE(mInputReceiver, nullptr)
1371 << "Cannot consume events from a window with no receiver";
1372 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1373 }
1374
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001375 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001376 if (mInputReceiver == nullptr) {
1377 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1378 return std::nullopt;
1379 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001380 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001381 }
1382
1383 void finishEvent(uint32_t sequenceNum) {
1384 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1385 mInputReceiver->finishEvent(sequenceNum);
1386 }
1387
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001388 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1389 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1390 mInputReceiver->sendTimeline(inputEventId, timeline);
1391 }
1392
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001393 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001394 if (mInputReceiver == nullptr) {
1395 return nullptr;
1396 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001397 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001398 }
1399
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001400 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001401 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001402 if (event == nullptr) {
1403 ADD_FAILURE() << "Consume failed : no event";
1404 return nullptr;
1405 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001406 if (event->getType() != InputEventType::MOTION) {
1407 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001408 return nullptr;
1409 }
1410 return static_cast<MotionEvent*>(event);
1411 }
1412
Arthur Hungb92218b2018-08-14 12:00:21 +08001413 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001414 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001415 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001416 return; // Can't receive events if the window does not have input channel
1417 }
1418 ASSERT_NE(nullptr, mInputReceiver)
1419 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001420 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001421 }
1422
chaviwaf87b3e2019-10-01 16:59:28 -07001423 sp<IBinder> getToken() { return mInfo.token; }
1424
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001425 const std::string& getName() { return mName; }
1426
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001427 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001428 mInfo.ownerPid = ownerPid;
1429 mInfo.ownerUid = ownerUid;
1430 }
1431
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001432 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001433
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001434 void destroyReceiver() { mInputReceiver = nullptr; }
1435
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001436 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1437
chaviwd1c23182019-12-20 18:44:56 -08001438private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001439 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001440 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001441 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001442 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001443 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001444};
1445
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001446std::atomic<int32_t> FakeWindowHandle::sId{1};
1447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001448static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001449 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001450 int32_t displayId = ADISPLAY_ID_NONE,
1451 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001452 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001453 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001454 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001455 KeyEvent event;
1456 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1457
1458 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001459 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001460 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1461 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001462
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001463 if (!allowKeyRepeat) {
1464 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1465 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001466 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001467 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001468}
1469
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001470static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1471 InputEventInjectionResult result =
1472 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1473 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1474 if (result != InputEventInjectionResult::TIMED_OUT) {
1475 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1476 }
1477}
1478
1479static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001480 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001481 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001482}
1483
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001484// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1485// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1486// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001487static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1488 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001489 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001490 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001491 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001492}
1493
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001494static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001495 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001496 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001497}
1498
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001500 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001501 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001502 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001503 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001504 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1505 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001506}
1507
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001508static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001509 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1510 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001511 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001512 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1513 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001514 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001515 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001516 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001517 MotionEventBuilder motionBuilder =
1518 MotionEventBuilder(action, source)
1519 .displayId(displayId)
1520 .eventTime(eventTime)
1521 .rawXCursorPosition(cursorPosition.x)
1522 .rawYCursorPosition(cursorPosition.y)
1523 .pointer(
1524 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1525 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1526 motionBuilder.downTime(eventTime);
1527 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001528
1529 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001530 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1531 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001532}
1533
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001534static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1535 int32_t displayId,
1536 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001537 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001538}
1539
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001540static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1541 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001542 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001543 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001544}
1545
Jackal Guof9696682018-10-05 12:23:23 +08001546static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1547 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1548 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001549 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001550 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1551 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001552
1553 return args;
1554}
1555
Josep del Riob3981622023-04-18 15:49:45 +00001556static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1557 int32_t displayId = ADISPLAY_ID_NONE) {
1558 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1559 // Define a valid key event.
1560 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001561 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001562 currentTime);
1563
1564 return args;
1565}
1566
1567static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1568 int32_t displayId = ADISPLAY_ID_NONE) {
1569 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1570 // Define a valid key event.
1571 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001572 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001573 AMETA_NONE, currentTime);
1574
1575 return args;
1576}
1577
Prabir Pradhan678438e2023-04-13 19:32:51 +00001578[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1579 int32_t displayId,
1580 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001581 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001582 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1583 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1584 }
1585
chaviwd1c23182019-12-20 18:44:56 -08001586 PointerProperties pointerProperties[pointerCount];
1587 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001588
chaviwd1c23182019-12-20 18:44:56 -08001589 for (size_t i = 0; i < pointerCount; i++) {
1590 pointerProperties[i].clear();
1591 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001592 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001593
chaviwd1c23182019-12-20 18:44:56 -08001594 pointerCoords[i].clear();
1595 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1596 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1597 }
Jackal Guof9696682018-10-05 12:23:23 +08001598
1599 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1600 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001601 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001602 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1603 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001604 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001605 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001606 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001607 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001608
1609 return args;
1610}
1611
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001612static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1613 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1614}
1615
chaviwd1c23182019-12-20 18:44:56 -08001616static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1617 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1618}
1619
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001620static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1621 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001622 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001623}
1624
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001625} // namespace
1626
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001627/**
1628 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1629 * broken channel.
1630 */
1631TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1632 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1633 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001634 sp<FakeWindowHandle>::make(application, mDispatcher,
1635 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001636
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001637 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001638
1639 // Window closes its channel, but the window remains.
1640 window->destroyReceiver();
1641 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1642}
1643
Arthur Hungb92218b2018-08-14 12:00:21 +08001644TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001646 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1647 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001648
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001653
1654 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001655 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001656}
1657
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001658TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1661 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001662
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001663 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001664 // Inject a MotionEvent to an unknown display.
1665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001666 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1668
1669 // Window should receive motion event.
1670 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1671}
1672
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001673/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001674 * Calling onWindowInfosChanged once should not cause any issues.
1675 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001676 * called twice.
1677 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001678TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001680 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1681 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001682 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001689
1690 // Window should receive motion event.
1691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1692}
1693
1694/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001695 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696 */
1697TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001699 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1700 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001702
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001703 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1704 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001706 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001709
1710 // Window should receive motion event.
1711 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1712}
1713
Arthur Hungb92218b2018-08-14 12:00:21 +08001714// The foreground window should receive the first touch down event.
1715TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001717 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001718 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001719 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001720 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001721
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001722 mDispatcher->onWindowInfosChanged(
1723 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001727
1728 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001729 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001730 windowSecond->assertNoEvents();
1731}
1732
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001733/**
1734 * Two windows: A top window, and a wallpaper behind the window.
1735 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1736 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001737 * 1. foregroundWindow <-- dup touch to wallpaper
1738 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001739 */
1740TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1742 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001743 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001744 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001745 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001746 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001747 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001748
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001749 mDispatcher->onWindowInfosChanged(
1750 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001752 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001753 {100, 200}))
1754 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1755
1756 // Both foreground window and its wallpaper should receive the touch down
1757 foregroundWindow->consumeMotionDown();
1758 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1759
1760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001761 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001762 ADISPLAY_ID_DEFAULT, {110, 200}))
1763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1764
1765 foregroundWindow->consumeMotionMove();
1766 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1767
1768 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001769 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001770 foregroundWindow->consumeMotionCancel();
1771 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1772 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1773}
1774
1775/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001776 * Two fingers down on the window, and lift off the first finger.
1777 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1778 * contains a single pointer.
1779 */
1780TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1782 sp<FakeWindowHandle> window =
1783 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001785 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001786 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1788 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1789 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001790 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001791 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1792 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1793 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1794 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001795 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001796 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1797 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1798 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1799 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1801 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1802 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1803
1804 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001805 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001806 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1807 window->consumeMotionEvent(
1808 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1809}
1810
1811/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001812 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1813 * with the following differences:
1814 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1815 * clean up the connection.
1816 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1817 * Ensure that there's no crash in the dispatcher.
1818 */
1819TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1821 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001822 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001823 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001824 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001825 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001826 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001827
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001828 mDispatcher->onWindowInfosChanged(
1829 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001831 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001832 {100, 200}))
1833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1834
1835 // Both foreground window and its wallpaper should receive the touch down
1836 foregroundWindow->consumeMotionDown();
1837 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1838
1839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001840 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001841 ADISPLAY_ID_DEFAULT, {110, 200}))
1842 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1843
1844 foregroundWindow->consumeMotionMove();
1845 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1846
1847 // Wallpaper closes its channel, but the window remains.
1848 wallpaperWindow->destroyReceiver();
1849 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1850
1851 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1852 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001853 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001854 foregroundWindow->consumeMotionCancel();
1855}
1856
Arthur Hungc539dbb2022-12-08 07:45:36 +00001857class ShouldSplitTouchFixture : public InputDispatcherTest,
1858 public ::testing::WithParamInterface<bool> {};
1859INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1860 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001861/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001862 * A single window that receives touch (on top), and a wallpaper window underneath it.
1863 * The top window gets a multitouch gesture.
1864 * Ensure that wallpaper gets the same gesture.
1865 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001866TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001868 sp<FakeWindowHandle> foregroundWindow =
1869 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1870 foregroundWindow->setDupTouchToWallpaper(true);
1871 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001872
1873 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001874 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001875 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001877 mDispatcher->onWindowInfosChanged(
1878 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879
1880 // Touch down on top window
1881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001882 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883 {100, 100}))
1884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1885
1886 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1889
1890 // Second finger down on the top window
1891 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001892 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001894 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1895 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 .build();
1897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001898 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899 InputEventInjectionSync::WAIT_FOR_RESULT))
1900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1901
Harry Cutts33476232023-01-30 19:57:29 +00001902 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1903 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001905
1906 const MotionEvent secondFingerUpEvent =
1907 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1908 .displayId(ADISPLAY_ID_DEFAULT)
1909 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001910 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1911 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001912 .build();
1913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001914 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001915 InputEventInjectionSync::WAIT_FOR_RESULT))
1916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1917 foregroundWindow->consumeMotionPointerUp(0);
1918 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1919
1920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001921 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001922 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1923 AINPUT_SOURCE_TOUCHSCREEN)
1924 .displayId(ADISPLAY_ID_DEFAULT)
1925 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001926 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001927 .x(100)
1928 .y(100))
1929 .build(),
1930 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1932 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1933 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934}
1935
1936/**
1937 * Two windows: a window on the left and window on the right.
1938 * A third window, wallpaper, is behind both windows, and spans both top windows.
1939 * The first touch down goes to the left window. A second pointer touches down on the right window.
1940 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1941 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1942 * ACTION_POINTER_DOWN(1).
1943 */
1944TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1946 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001947 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001949 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950
1951 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001952 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001953 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001954 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955
1956 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001957 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001959 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001961 mDispatcher->onWindowInfosChanged(
1962 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1963 {},
1964 0,
1965 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001966
1967 // Touch down on left window
1968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001969 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001970 {100, 100}))
1971 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1972
1973 // Both foreground window and its wallpaper should receive the touch down
1974 leftWindow->consumeMotionDown();
1975 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1976
1977 // Second finger down on the right window
1978 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001979 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001981 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1982 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001983 .build();
1984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001985 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001986 InputEventInjectionSync::WAIT_FOR_RESULT))
1987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1988
1989 leftWindow->consumeMotionMove();
1990 // Since the touch is split, right window gets ACTION_DOWN
1991 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001992 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993 expectedWallpaperFlags);
1994
1995 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001996 mDispatcher->onWindowInfosChanged(
1997 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 leftWindow->consumeMotionCancel();
1999 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2000 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2001
2002 // The pointer that's still down on the right window moves, and goes to the right window only.
2003 // As far as the dispatcher's concerned though, both pointers are still present.
2004 const MotionEvent secondFingerMoveEvent =
2005 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2006 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002007 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2008 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009 .build();
2010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002011 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 InputEventInjectionSync::WAIT_FOR_RESULT));
2013 rightWindow->consumeMotionMove();
2014
2015 leftWindow->assertNoEvents();
2016 rightWindow->assertNoEvents();
2017 wallpaperWindow->assertNoEvents();
2018}
2019
Arthur Hungc539dbb2022-12-08 07:45:36 +00002020/**
2021 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2022 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2023 * The right window should receive ACTION_DOWN.
2024 */
2025TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002027 sp<FakeWindowHandle> leftWindow =
2028 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2029 leftWindow->setFrame(Rect(0, 0, 200, 200));
2030 leftWindow->setDupTouchToWallpaper(true);
2031 leftWindow->setSlippery(true);
2032
2033 sp<FakeWindowHandle> rightWindow =
2034 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2035 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002036
2037 sp<FakeWindowHandle> wallpaperWindow =
2038 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2039 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002040
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002041 mDispatcher->onWindowInfosChanged(
2042 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2043 {},
2044 0,
2045 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002046
Arthur Hungc539dbb2022-12-08 07:45:36 +00002047 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002049 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052
2053 // Both foreground window and its wallpaper should receive the touch down
2054 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002055 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2056
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002059 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002060 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2062
Arthur Hungc539dbb2022-12-08 07:45:36 +00002063 leftWindow->consumeMotionCancel();
2064 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2065 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002066}
2067
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002068/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002069 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2070 * interactive, it might stop sending this flag.
2071 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2072 * to have a consistent input stream.
2073 *
2074 * Test procedure:
2075 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2076 * DOWN (new gesture).
2077 *
2078 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2079 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2080 *
2081 * We technically just need a single window here, but we are using two windows (spy on top and a
2082 * regular window below) to emulate the actual situation where it happens on the device.
2083 */
2084TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2086 sp<FakeWindowHandle> spyWindow =
2087 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2088 spyWindow->setFrame(Rect(0, 0, 200, 200));
2089 spyWindow->setTrustedOverlay(true);
2090 spyWindow->setSpy(true);
2091
2092 sp<FakeWindowHandle> window =
2093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2094 window->setFrame(Rect(0, 0, 200, 200));
2095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002096 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002097 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002098
2099 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002100 mDispatcher->notifyMotion(
2101 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2102 .deviceId(touchDeviceId)
2103 .policyFlags(DEFAULT_POLICY_FLAGS)
2104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2105 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106
Prabir Pradhan678438e2023-04-13 19:32:51 +00002107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2108 .deviceId(touchDeviceId)
2109 .policyFlags(DEFAULT_POLICY_FLAGS)
2110 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2111 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2112 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002113 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2114 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2115 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2116 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2117
2118 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002119 mDispatcher->notifyMotion(
2120 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2121 .deviceId(touchDeviceId)
2122 .policyFlags(0)
2123 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2124 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2125 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2127 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2128
2129 // We don't need to reset the device to reproduce the issue, but the reset event typically
2130 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002131 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002132
2133 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002134 mDispatcher->notifyMotion(
2135 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2136 .deviceId(touchDeviceId)
2137 .policyFlags(DEFAULT_POLICY_FLAGS)
2138 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2139 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002140 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2141 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2142
2143 // No more events
2144 spyWindow->assertNoEvents();
2145 window->assertNoEvents();
2146}
2147
2148/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002149 * Two windows: a window on the left and a window on the right.
2150 * Mouse is hovered from the right window into the left window.
2151 * Next, we tap on the left window, where the cursor was last seen.
2152 * The second tap is done onto the right window.
2153 * The mouse and tap are from two different devices.
2154 * We technically don't need to set the downtime / eventtime for these events, but setting these
2155 * explicitly helps during debugging.
2156 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2157 * In the buggy implementation, a tap on the right window would cause a crash.
2158 */
2159TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2161 sp<FakeWindowHandle> leftWindow =
2162 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2163 leftWindow->setFrame(Rect(0, 0, 200, 200));
2164
2165 sp<FakeWindowHandle> rightWindow =
2166 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2167 rightWindow->setFrame(Rect(200, 0, 400, 200));
2168
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002169 mDispatcher->onWindowInfosChanged(
2170 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002171 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2172 // stale.
2173 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2174 const int32_t mouseDeviceId = 6;
2175 const int32_t touchDeviceId = 4;
2176 // Move the cursor from right
2177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002179 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2180 AINPUT_SOURCE_MOUSE)
2181 .deviceId(mouseDeviceId)
2182 .downTime(baseTime + 10)
2183 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002184 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 .build()));
2186 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2187
2188 // .. to the left window
2189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002190 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002191 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2192 AINPUT_SOURCE_MOUSE)
2193 .deviceId(mouseDeviceId)
2194 .downTime(baseTime + 10)
2195 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002196 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002197 .build()));
2198 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2199 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2200 // Now tap the left window
2201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002202 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002203 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2204 AINPUT_SOURCE_TOUCHSCREEN)
2205 .deviceId(touchDeviceId)
2206 .downTime(baseTime + 40)
2207 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002208 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002209 .build()));
2210 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2211 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2212
2213 // release tap
2214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002215 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002216 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2217 AINPUT_SOURCE_TOUCHSCREEN)
2218 .deviceId(touchDeviceId)
2219 .downTime(baseTime + 40)
2220 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002221 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002222 .build()));
2223 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2224
2225 // Tap the window on the right
2226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002227 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002228 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2229 AINPUT_SOURCE_TOUCHSCREEN)
2230 .deviceId(touchDeviceId)
2231 .downTime(baseTime + 60)
2232 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002233 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002234 .build()));
2235 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2236
2237 // release tap
2238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2241 AINPUT_SOURCE_TOUCHSCREEN)
2242 .deviceId(touchDeviceId)
2243 .downTime(baseTime + 60)
2244 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002245 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002246 .build()));
2247 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2248
2249 // No more events
2250 leftWindow->assertNoEvents();
2251 rightWindow->assertNoEvents();
2252}
2253
2254/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002255 * Start hovering in a window. While this hover is still active, make another window appear on top.
2256 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2257 * While the top window is present, the hovering is stopped.
2258 * Later, hovering gets resumed again.
2259 * Ensure that new hover gesture is handled correctly.
2260 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2261 * to the window that's currently being hovered over.
2262 */
2263TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2264 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2265 sp<FakeWindowHandle> window =
2266 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2267 window->setFrame(Rect(0, 0, 200, 200));
2268
2269 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002270 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002271
2272 // Start hovering in the window
2273 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2274 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2275 .build());
2276 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2277
2278 // Now, an obscuring window appears!
2279 sp<FakeWindowHandle> obscuringWindow =
2280 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2281 ADISPLAY_ID_DEFAULT,
2282 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2283 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2284 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2285 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2286 obscuringWindow->setNoInputChannel(true);
2287 obscuringWindow->setFocusable(false);
2288 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002289 mDispatcher->onWindowInfosChanged(
2290 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002291
2292 // While this new obscuring window is present, the hovering is stopped
2293 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2294 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2295 .build());
2296 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2297
2298 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002299 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002300
2301 // And a new hover gesture starts.
2302 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2303 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2304 .build());
2305 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2306}
2307
2308/**
2309 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2310 * the obscuring window.
2311 */
2312TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2313 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2314 sp<FakeWindowHandle> window =
2315 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2316 window->setFrame(Rect(0, 0, 200, 200));
2317
2318 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002319 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002320
2321 // Start hovering in the window
2322 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2323 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2324 .build());
2325 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2326
2327 // Now, an obscuring window appears!
2328 sp<FakeWindowHandle> obscuringWindow =
2329 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2330 ADISPLAY_ID_DEFAULT,
2331 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2332 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2333 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2334 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2335 obscuringWindow->setNoInputChannel(true);
2336 obscuringWindow->setFocusable(false);
2337 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002338 mDispatcher->onWindowInfosChanged(
2339 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002340
2341 // While this new obscuring window is present, the hovering continues. The event can't go to the
2342 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2343 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2344 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2345 .build());
2346 obscuringWindow->assertNoEvents();
2347 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2348
2349 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002350 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002351
2352 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2353 // so it should generate a HOVER_ENTER
2354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2355 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2356 .build());
2357 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2358
2359 // Now the MOVE should be getting dispatched normally
2360 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2361 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2362 .build());
2363 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2364}
2365
2366/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002367 * Two windows: a window on the left and a window on the right.
2368 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2369 * down. Then, on the left window, also place second touch pointer down.
2370 * This test tries to reproduce a crash.
2371 * In the buggy implementation, second pointer down on the left window would cause a crash.
2372 */
2373TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2375 sp<FakeWindowHandle> leftWindow =
2376 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2377 leftWindow->setFrame(Rect(0, 0, 200, 200));
2378
2379 sp<FakeWindowHandle> rightWindow =
2380 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2381 rightWindow->setFrame(Rect(200, 0, 400, 200));
2382
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002383 mDispatcher->onWindowInfosChanged(
2384 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002385
2386 const int32_t touchDeviceId = 4;
2387 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002388
2389 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2391 .deviceId(mouseDeviceId)
2392 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2393 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002394 leftWindow->consumeMotionEvent(
2395 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2396
2397 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002398 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2399 .deviceId(mouseDeviceId)
2400 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2401 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2402 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002403
2404 leftWindow->consumeMotionEvent(
2405 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2406 leftWindow->consumeMotionEvent(
2407 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2408
Prabir Pradhan678438e2023-04-13 19:32:51 +00002409 mDispatcher->notifyMotion(
2410 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2411 .deviceId(mouseDeviceId)
2412 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2413 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2414 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2415 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002416 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2417
2418 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2420 .deviceId(touchDeviceId)
2421 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2422 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002423 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2424
2425 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2426
2427 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002428 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2429 .deviceId(touchDeviceId)
2430 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2431 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2432 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002433 leftWindow->consumeMotionEvent(
2434 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2435 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2436 // current implementation.
2437 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2438 rightWindow->consumeMotionEvent(
2439 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2440
2441 leftWindow->assertNoEvents();
2442 rightWindow->assertNoEvents();
2443}
2444
2445/**
2446 * On a single window, use two different devices: mouse and touch.
2447 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2448 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2449 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2450 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2451 * represent a new gesture.
2452 */
2453TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2455 sp<FakeWindowHandle> window =
2456 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2457 window->setFrame(Rect(0, 0, 400, 400));
2458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002460
2461 const int32_t touchDeviceId = 4;
2462 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002463
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002464 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002465 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2466 .deviceId(touchDeviceId)
2467 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2468 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002469 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002470 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, 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 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002476 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2477 .deviceId(touchDeviceId)
2478 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2479 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2480 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002481 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2482 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2483 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2484
2485 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2487 .deviceId(mouseDeviceId)
2488 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2489 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2490 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002491
2492 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002493 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002494 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2495
Prabir Pradhan678438e2023-04-13 19:32:51 +00002496 mDispatcher->notifyMotion(
2497 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2498 .deviceId(mouseDeviceId)
2499 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2500 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2501 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2502 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002503 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2504
2505 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002506 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2507 .deviceId(touchDeviceId)
2508 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2509 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2510 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002511 // The pointer_down event should be ignored
2512 window->assertNoEvents();
2513}
2514
2515/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002516 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2517 * the injected event.
2518 */
2519TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2521 sp<FakeWindowHandle> window =
2522 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2523 window->setFrame(Rect(0, 0, 400, 400));
2524
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002525 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002526
2527 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002528 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2529 // completion.
2530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002531 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002532 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2533 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002534 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002535 .build()));
2536 window->consumeMotionEvent(
2537 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2538
2539 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2540 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2542 .deviceId(touchDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2544 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002545
2546 window->consumeMotionEvent(
2547 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2548 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2549}
2550
2551/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002552 * This test is similar to the test above, but the sequence of injected events is different.
2553 *
2554 * Two windows: a window on the left and a window on the right.
2555 * Mouse is hovered over the left window.
2556 * Next, we tap on the left window, where the cursor was last seen.
2557 *
2558 * After that, we inject one finger down onto the right window, and then a second finger down onto
2559 * the left window.
2560 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2561 * window (first), and then another on the left window (second).
2562 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2563 * In the buggy implementation, second finger down on the left window would cause a crash.
2564 */
2565TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2567 sp<FakeWindowHandle> leftWindow =
2568 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2569 leftWindow->setFrame(Rect(0, 0, 200, 200));
2570
2571 sp<FakeWindowHandle> rightWindow =
2572 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2573 rightWindow->setFrame(Rect(200, 0, 400, 200));
2574
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002575 mDispatcher->onWindowInfosChanged(
2576 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002577
2578 const int32_t mouseDeviceId = 6;
2579 const int32_t touchDeviceId = 4;
2580 // Hover over the left window. Keep the cursor there.
2581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002582 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002583 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2584 AINPUT_SOURCE_MOUSE)
2585 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002586 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002587 .build()));
2588 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2589
2590 // Tap on left window
2591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002592 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002593 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2594 AINPUT_SOURCE_TOUCHSCREEN)
2595 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002596 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002597 .build()));
2598
2599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002600 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002601 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2602 AINPUT_SOURCE_TOUCHSCREEN)
2603 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002604 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002605 .build()));
2606 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2607 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2608 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2609
2610 // First finger down on right window
2611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002612 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002613 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2614 AINPUT_SOURCE_TOUCHSCREEN)
2615 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002616 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002617 .build()));
2618 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2619
2620 // Second finger down on the left window
2621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002622 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002623 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2624 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002625 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2626 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002627 .build()));
2628 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2629 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2630
2631 // No more events
2632 leftWindow->assertNoEvents();
2633 rightWindow->assertNoEvents();
2634}
2635
2636/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002637 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2638 * While the touch is down, new hover events from the stylus device should be ignored. After the
2639 * touch is gone, stylus hovering should start working again.
2640 */
2641TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2643 sp<FakeWindowHandle> window =
2644 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2645 window->setFrame(Rect(0, 0, 200, 200));
2646
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002647 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002648
2649 const int32_t stylusDeviceId = 5;
2650 const int32_t touchDeviceId = 4;
2651 // Start hovering with stylus
2652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002653 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002654 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2655 AINPUT_SOURCE_STYLUS)
2656 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002657 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002658 .build()));
2659 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2660
2661 // Finger down on the window
2662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002663 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002664 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2665 AINPUT_SOURCE_TOUCHSCREEN)
2666 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002667 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002668 .build()));
2669 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2670 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2671
2672 // Try to continue hovering with stylus. Since we are already down, injection should fail
2673 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002674 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002675 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2676 AINPUT_SOURCE_STYLUS)
2677 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002679 .build()));
2680 // No event should be sent. This event should be ignored because a pointer from another device
2681 // is already down.
2682
2683 // Lift up the finger
2684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002685 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002686 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2687 AINPUT_SOURCE_TOUCHSCREEN)
2688 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002689 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002690 .build()));
2691 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2692
2693 // Now that the touch is gone, stylus hovering should start working again
2694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002695 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002696 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2697 AINPUT_SOURCE_STYLUS)
2698 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002699 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002700 .build()));
2701 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2702 // No more events
2703 window->assertNoEvents();
2704}
2705
2706/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002707 * A spy window above a window with no input channel.
2708 * Start hovering with a stylus device, and then tap with it.
2709 * Ensure spy window receives the entire sequence.
2710 */
2711TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2713 sp<FakeWindowHandle> spyWindow =
2714 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2715 spyWindow->setFrame(Rect(0, 0, 200, 200));
2716 spyWindow->setTrustedOverlay(true);
2717 spyWindow->setSpy(true);
2718 sp<FakeWindowHandle> window =
2719 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2720 window->setNoInputChannel(true);
2721 window->setFrame(Rect(0, 0, 200, 200));
2722
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002723 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002724
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002725 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2727 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2728 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002729 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2730 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, 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_HOVER_EXIT));
2735
2736 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, 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_DOWN));
2741
2742 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, 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_UP));
2747
2748 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2750 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2751 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002752 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2753 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002754 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2755 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2756 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002757 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2758
2759 // No more events
2760 spyWindow->assertNoEvents();
2761 window->assertNoEvents();
2762}
2763
2764/**
2765 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2766 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2767 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2768 * While the mouse is down, new move events from the touch device should be ignored.
2769 */
2770TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2772 sp<FakeWindowHandle> spyWindow =
2773 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2774 spyWindow->setFrame(Rect(0, 0, 200, 200));
2775 spyWindow->setTrustedOverlay(true);
2776 spyWindow->setSpy(true);
2777 sp<FakeWindowHandle> window =
2778 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2779 window->setFrame(Rect(0, 0, 200, 200));
2780
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002781 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002782
2783 const int32_t mouseDeviceId = 7;
2784 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002785
2786 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2788 .deviceId(mouseDeviceId)
2789 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2790 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002791 spyWindow->consumeMotionEvent(
2792 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2793 window->consumeMotionEvent(
2794 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2795
2796 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2798 .deviceId(touchDeviceId)
2799 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2800 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002801 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2802 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2803 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2804 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2805
Prabir Pradhan678438e2023-04-13 19:32:51 +00002806 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2807 .deviceId(touchDeviceId)
2808 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2809 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002810 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2811 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2812
2813 // Pilfer the stream
2814 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2815 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2816
Prabir Pradhan678438e2023-04-13 19:32:51 +00002817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2818 .deviceId(touchDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2820 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2822
2823 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2825 .deviceId(mouseDeviceId)
2826 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2828 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002829
2830 spyWindow->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2832 spyWindow->consumeMotionEvent(
2833 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2834 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2835
Prabir Pradhan678438e2023-04-13 19:32:51 +00002836 mDispatcher->notifyMotion(
2837 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2838 .deviceId(mouseDeviceId)
2839 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2840 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2842 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002843 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2844 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2845
2846 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2848 .deviceId(mouseDeviceId)
2849 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2850 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2851 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2853 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2854
2855 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2857 .deviceId(touchDeviceId)
2858 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2859 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002860
2861 // No more events
2862 spyWindow->assertNoEvents();
2863 window->assertNoEvents();
2864}
2865
2866/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002867 * On the display, have a single window, and also an area where there's no window.
2868 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2869 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2870 */
2871TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2873 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002874 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002875
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002876 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002877
2878 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002879 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002880
2881 mDispatcher->waitForIdle();
2882 window->assertNoEvents();
2883
2884 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002885 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002886 mDispatcher->waitForIdle();
2887 window->consumeMotionDown();
2888}
2889
2890/**
2891 * Same test as above, but instead of touching the empty space, the first touch goes to
2892 * non-touchable window.
2893 */
2894TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2895 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2896 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002897 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002898 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2899 window1->setTouchable(false);
2900 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002901 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002902 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2903
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002904 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002905
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002906 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002907 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002908
2909 mDispatcher->waitForIdle();
2910 window1->assertNoEvents();
2911 window2->assertNoEvents();
2912
2913 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002914 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002915 mDispatcher->waitForIdle();
2916 window2->consumeMotionDown();
2917}
2918
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002919/**
2920 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2921 * to the event time of the first ACTION_DOWN sent to the particular window.
2922 */
2923TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2925 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002926 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002927 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2928 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002929 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002930 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2931
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002932 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002933
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002934 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002935 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002936
2937 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002938
2939 MotionEvent* motionEvent1 = window1->consumeMotion();
2940 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002941 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002942 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
2943 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002944
2945 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002946 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002947 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002948 MotionEvent* motionEvent2 = window2->consumeMotion();
2949 ASSERT_NE(motionEvent2, nullptr);
2950 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002951 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002952 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002953
2954 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002955 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002956 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002957 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002958
2959 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002960 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002961 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002962 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002963
2964 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2965 window1->consumeMotionMove();
2966 window1->assertNoEvents();
2967
2968 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002969 mDispatcher->notifyMotion(
2970 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002971 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002972 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002973
Prabir Pradhan678438e2023-04-13 19:32:51 +00002974 mDispatcher->notifyMotion(
2975 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002976 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002977 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002978}
2979
Garfield Tandf26e862020-07-01 20:18:19 -07002980TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002982 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002983 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002984 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002985 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002986 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002987 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002988
2989 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2990
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002991 mDispatcher->onWindowInfosChanged(
2992 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07002993
2994 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002996 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07002997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2998 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003000 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003001 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003002
3003 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003005 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003006 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3007 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003008 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003009 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003010 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3011 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003012
3013 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003015 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003016 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3017 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003018 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003019 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003020 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3021 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003022
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003024 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003025 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3026 AINPUT_SOURCE_MOUSE)
3027 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3028 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003029 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003030 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003031 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003034 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003035 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3036 AINPUT_SOURCE_MOUSE)
3037 .buttonState(0)
3038 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003039 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003040 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003041 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003044 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003045 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3046 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003047 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003048 .build()));
3049 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3050
3051 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003053 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003054 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3055 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003056 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003057 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003058 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003059
3060 // No more events
3061 windowLeft->assertNoEvents();
3062 windowRight->assertNoEvents();
3063}
3064
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003065/**
3066 * Put two fingers down (and don't release them) and click the mouse button.
3067 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3068 * currently active gesture should be canceled, and the new one should proceed.
3069 */
3070TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3072 sp<FakeWindowHandle> window =
3073 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3074 window->setFrame(Rect(0, 0, 600, 800));
3075
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003076 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003077
3078 const int32_t touchDeviceId = 4;
3079 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003080
3081 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003082 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3083 .deviceId(touchDeviceId)
3084 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3085 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003086
Prabir Pradhan678438e2023-04-13 19:32:51 +00003087 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3088 .deviceId(touchDeviceId)
3089 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3090 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3091 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003092 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3093 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3094
3095 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3097 .deviceId(mouseDeviceId)
3098 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3099 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3100 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3102 WithPointerCount(2u)));
3103 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3104
Prabir Pradhan678438e2023-04-13 19:32:51 +00003105 mDispatcher->notifyMotion(
3106 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3107 .deviceId(mouseDeviceId)
3108 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3109 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3110 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3113
3114 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3115 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3117 .deviceId(touchDeviceId)
3118 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3119 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3120 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003121 window->assertNoEvents();
3122}
3123
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003124TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3125 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3126
3127 sp<FakeWindowHandle> spyWindow =
3128 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3129 spyWindow->setFrame(Rect(0, 0, 600, 800));
3130 spyWindow->setTrustedOverlay(true);
3131 spyWindow->setSpy(true);
3132 sp<FakeWindowHandle> window =
3133 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3134 window->setFrame(Rect(0, 0, 600, 800));
3135
3136 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003137 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003138
3139 // Send mouse cursor to the window
3140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003141 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003142 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3143 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003144 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003145 .build()));
3146
3147 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3148 WithSource(AINPUT_SOURCE_MOUSE)));
3149 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3150 WithSource(AINPUT_SOURCE_MOUSE)));
3151
3152 window->assertNoEvents();
3153 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003154}
3155
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003156TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3158
3159 sp<FakeWindowHandle> spyWindow =
3160 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3161 spyWindow->setFrame(Rect(0, 0, 600, 800));
3162 spyWindow->setTrustedOverlay(true);
3163 spyWindow->setSpy(true);
3164 sp<FakeWindowHandle> window =
3165 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3166 window->setFrame(Rect(0, 0, 600, 800));
3167
3168 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003169 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003170
3171 // Send mouse cursor to the window
3172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003173 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003174 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3175 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003176 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003177 .build()));
3178
3179 // Move mouse cursor
3180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003181 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003182 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3183 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003184 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003185 .build()));
3186
3187 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3188 WithSource(AINPUT_SOURCE_MOUSE)));
3189 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3190 WithSource(AINPUT_SOURCE_MOUSE)));
3191 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3192 WithSource(AINPUT_SOURCE_MOUSE)));
3193 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3194 WithSource(AINPUT_SOURCE_MOUSE)));
3195 // Touch down on the window
3196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003197 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003198 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3199 AINPUT_SOURCE_TOUCHSCREEN)
3200 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003201 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003202 .build()));
3203 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3204 WithSource(AINPUT_SOURCE_MOUSE)));
3205 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3206 WithSource(AINPUT_SOURCE_MOUSE)));
3207 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3208 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3209 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3210 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3211
3212 // pilfer the motion, retaining the gesture on the spy window.
3213 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3214 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3215 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3216
3217 // Touch UP on the window
3218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003219 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003220 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3221 AINPUT_SOURCE_TOUCHSCREEN)
3222 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003223 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003224 .build()));
3225 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3226 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3227
3228 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3229 // to send a new gesture. It should again go to both windows (spy and the window below), just
3230 // like the first gesture did, before pilfering. The window configuration has not changed.
3231
3232 // One more tap - DOWN
3233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003234 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003235 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3236 AINPUT_SOURCE_TOUCHSCREEN)
3237 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003238 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003239 .build()));
3240 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3241 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3242 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3243 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3244
3245 // Touch UP on the window
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003248 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003252 .build()));
3253 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3254 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3255 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3256 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3257
3258 window->assertNoEvents();
3259 spyWindow->assertNoEvents();
3260}
3261
Garfield Tandf26e862020-07-01 20:18:19 -07003262// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3263// directly in this test.
3264TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003266 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003267 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003268 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003269
3270 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3271
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003272 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003273
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003275 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003276 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3277 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003278 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003279 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003280 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003281 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003283 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003284 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3285 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003286 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003287 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003288 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3289 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003290
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003292 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003293 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3294 AINPUT_SOURCE_MOUSE)
3295 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3296 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003297 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003298 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003299 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003300
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003302 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003303 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3304 AINPUT_SOURCE_MOUSE)
3305 .buttonState(0)
3306 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003307 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003308 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003309 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003310
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003313 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3314 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003315 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003316 .build()));
3317 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3318
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003319 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3320 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3321 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003322 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003323 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3324 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003325 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003326 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003327 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003328}
3329
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003330/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003331 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3332 * is generated.
3333 */
3334TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3335 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3336 sp<FakeWindowHandle> window =
3337 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3338 window->setFrame(Rect(0, 0, 1200, 800));
3339
3340 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3341
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003342 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003343
3344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003346 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3347 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003348 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003349 .build()));
3350 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3351
3352 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003353 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003354 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3355}
3356
3357/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003358 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3359 */
3360TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3362 sp<FakeWindowHandle> window =
3363 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3364 window->setFrame(Rect(0, 0, 100, 100));
3365
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003366 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003367
3368 const int32_t mouseDeviceId = 7;
3369 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003370
3371 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003372 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3373 .deviceId(mouseDeviceId)
3374 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3375 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003376 window->consumeMotionEvent(
3377 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3378
3379 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3381 .deviceId(touchDeviceId)
3382 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3383 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003384
3385 window->consumeMotionEvent(
3386 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3387 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3388}
3389
3390/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003391 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003392 * The tap causes a HOVER_EXIT event to be generated because the current event
3393 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003394 */
3395TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3397 sp<FakeWindowHandle> window =
3398 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3399 window->setFrame(Rect(0, 0, 100, 100));
3400
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003401 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003402
3403 // Inject a hover_move from mouse.
3404 NotifyMotionArgs motionArgs =
3405 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3406 ADISPLAY_ID_DEFAULT, {{50, 50}});
3407 motionArgs.xCursorPosition = 50;
3408 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003409 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003410 ASSERT_NO_FATAL_FAILURE(
3411 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3412 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003413
3414 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003415 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3416 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3417 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003418 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003419 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3420 WithSource(AINPUT_SOURCE_MOUSE))));
3421
3422 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003423 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3424 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3425
Prabir Pradhan678438e2023-04-13 19:32:51 +00003426 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3427 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003428 ASSERT_NO_FATAL_FAILURE(
3429 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3430 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3431}
3432
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003433TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3435 sp<FakeWindowHandle> windowDefaultDisplay =
3436 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3437 ADISPLAY_ID_DEFAULT);
3438 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3439 sp<FakeWindowHandle> windowSecondDisplay =
3440 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3441 SECOND_DISPLAY_ID);
3442 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3443
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003444 mDispatcher->onWindowInfosChanged(
3445 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003446
3447 // Set cursor position in window in default display and check that hover enter and move
3448 // events are generated.
3449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003450 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003451 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3452 AINPUT_SOURCE_MOUSE)
3453 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003454 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003455 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003456 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003457
3458 // Remove all windows in secondary display and check that no event happens on window in
3459 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003460 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3461
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003462 windowDefaultDisplay->assertNoEvents();
3463
3464 // Move cursor position in window in default display and check that only hover move
3465 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003466 mDispatcher->onWindowInfosChanged(
3467 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003468 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(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003474 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003475 windowDefaultDisplay->consumeMotionEvent(
3476 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3477 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003478 windowDefaultDisplay->assertNoEvents();
3479}
3480
Garfield Tan00f511d2019-06-12 16:55:40 -07003481TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003482 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003483
3484 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003485 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003486 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003487 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003488 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003489 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003490
3491 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3492
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003493 mDispatcher->onWindowInfosChanged(
3494 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003495
3496 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3497 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003499 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003500 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003501 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003502 windowRight->assertNoEvents();
3503}
3504
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003505TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003507 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3508 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003509 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003510
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003511 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003512 setFocusedWindow(window);
3513
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003514 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003515
Prabir Pradhan678438e2023-04-13 19:32:51 +00003516 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003517
3518 // Window should receive key down event.
3519 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3520
3521 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3522 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003523 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003524 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003525 AKEY_EVENT_FLAG_CANCELED);
3526}
3527
3528TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003530 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3531 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003532
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003533 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003534
Prabir Pradhan678438e2023-04-13 19:32:51 +00003535 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3536 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003537
3538 // Window should receive motion down event.
3539 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3540
3541 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3542 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003543 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003544 window->consumeMotionEvent(
3545 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003546}
3547
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003548TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3551 "Fake Window", ADISPLAY_ID_DEFAULT);
3552
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003553 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003554
3555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3556 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3557 .build());
3558
3559 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3560
3561 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3562 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3563 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3564
3565 // After the device has been reset, a new hovering stream can be sent to the window
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3568 .build());
3569 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3570}
3571
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003572TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3573 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003574 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3575 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003576 window->setFocusable(true);
3577
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003578 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003579 setFocusedWindow(window);
3580
3581 window->consumeFocusEvent(true);
3582
Prabir Pradhan678438e2023-04-13 19:32:51 +00003583 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003584 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3585 const nsecs_t injectTime = keyArgs.eventTime;
3586 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003587 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003588 // The dispatching time should be always greater than or equal to intercept key timeout.
3589 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3590 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3591 std::chrono::nanoseconds(interceptKeyTimeout).count());
3592}
3593
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003594/**
3595 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3596 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003597TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003599 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3600 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003601 window->setFocusable(true);
3602
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003603 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003604 setFocusedWindow(window);
3605
3606 window->consumeFocusEvent(true);
3607
Prabir Pradhan678438e2023-04-13 19:32:51 +00003608 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003609 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003610
3611 // Set a value that's significantly larger than the default consumption timeout. If the
3612 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3613 mFakePolicy->setInterceptKeyTimeout(600ms);
3614 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3615 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003616 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3617}
3618
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003619/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003620 * Two windows. First is a regular window. Second does not overlap with the first, and has
3621 * WATCH_OUTSIDE_TOUCH.
3622 * Both windows are owned by the same UID.
3623 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3624 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3625 */
3626TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3628 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3629 "First Window", ADISPLAY_ID_DEFAULT);
3630 window->setFrame(Rect{0, 0, 100, 100});
3631
3632 sp<FakeWindowHandle> outsideWindow =
3633 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3634 ADISPLAY_ID_DEFAULT);
3635 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3636 outsideWindow->setWatchOutsideTouch(true);
3637 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003638 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003639
3640 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003641 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3642 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3643 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003644 window->consumeMotionDown();
3645 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3646 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3647 outsideWindow->consumeMotionEvent(
3648 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3649}
3650
3651/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003652 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3653 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3654 * ACTION_OUTSIDE event is sent per gesture.
3655 */
3656TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3657 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3658 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003659 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3660 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003661 window->setWatchOutsideTouch(true);
3662 window->setFrame(Rect{0, 0, 100, 100});
3663 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003664 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3665 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003666 secondWindow->setFrame(Rect{100, 100, 200, 200});
3667 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003668 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3669 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003670 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003671 mDispatcher->onWindowInfosChanged(
3672 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003673
3674 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003675 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3676 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3677 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003678 window->assertNoEvents();
3679 secondWindow->assertNoEvents();
3680
3681 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3682 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003683 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3684 ADISPLAY_ID_DEFAULT,
3685 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003686 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3687 window->consumeMotionEvent(
3688 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003689 secondWindow->consumeMotionDown();
3690 thirdWindow->assertNoEvents();
3691
3692 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3693 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003694 mDispatcher->notifyMotion(
3695 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3696 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003697 window->assertNoEvents();
3698 secondWindow->consumeMotionMove();
3699 thirdWindow->consumeMotionDown();
3700}
3701
Prabir Pradhan814fe082022-07-22 20:22:18 +00003702TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3705 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003706 window->setFocusable(true);
3707
Patrick Williamsd828f302023-04-28 17:52:08 -05003708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003709 setFocusedWindow(window);
3710
3711 window->consumeFocusEvent(true);
3712
Prabir Pradhan678438e2023-04-13 19:32:51 +00003713 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3714 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3715 mDispatcher->notifyKey(keyDown);
3716 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003717
3718 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3719 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3720
3721 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003722 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003723
3724 window->consumeFocusEvent(false);
3725
Prabir Pradhan678438e2023-04-13 19:32:51 +00003726 mDispatcher->notifyKey(keyDown);
3727 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003728 window->assertNoEvents();
3729}
3730
Arthur Hung96483742022-11-15 03:30:48 +00003731TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3734 "Fake Window", ADISPLAY_ID_DEFAULT);
3735 // Ensure window is non-split and have some transform.
3736 window->setPreventSplitting(true);
3737 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003739
3740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003741 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00003742 {50, 50}))
3743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3744 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3745
3746 const MotionEvent secondFingerDownEvent =
3747 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3748 .displayId(ADISPLAY_ID_DEFAULT)
3749 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003750 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3751 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003752 .build();
3753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003754 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00003755 InputEventInjectionSync::WAIT_FOR_RESULT))
3756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3757
3758 const MotionEvent* event = window->consumeMotion();
3759 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3760 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3761 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3762 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3763 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3764}
3765
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003766/**
3767 * Two windows: a splittable and a non-splittable.
3768 * The non-splittable window shouldn't receive any "incomplete" gestures.
3769 * Send the first pointer to the splittable window, and then touch the non-splittable window.
3770 * The second pointer should be dropped because the initial window is splittable, so it won't get
3771 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
3772 * "incomplete" gestures.
3773 */
3774TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
3775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3776 sp<FakeWindowHandle> leftWindow =
3777 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
3778 ADISPLAY_ID_DEFAULT);
3779 leftWindow->setPreventSplitting(false);
3780 leftWindow->setFrame(Rect(0, 0, 100, 100));
3781 sp<FakeWindowHandle> rightWindow =
3782 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
3783 ADISPLAY_ID_DEFAULT);
3784 rightWindow->setPreventSplitting(true);
3785 rightWindow->setFrame(Rect(100, 100, 200, 200));
3786 mDispatcher->onWindowInfosChanged(
3787 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3788
3789 // Touch down on left, splittable window
3790 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3791 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3792 .build());
3793 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3794
3795 mDispatcher->notifyMotion(
3796 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3797 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3798 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
3799 .build());
3800 leftWindow->assertNoEvents();
3801 rightWindow->assertNoEvents();
3802}
3803
Harry Cuttsb166c002023-05-09 13:06:05 +00003804TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3806 sp<FakeWindowHandle> window =
3807 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3808 window->setFrame(Rect(0, 0, 400, 400));
3809 sp<FakeWindowHandle> trustedOverlay =
3810 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3811 ADISPLAY_ID_DEFAULT);
3812 trustedOverlay->setSpy(true);
3813 trustedOverlay->setTrustedOverlay(true);
3814
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003815 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003816
3817 // Start a three-finger touchpad swipe
3818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3819 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3820 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3821 .build());
3822 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3823 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3824 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3825 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3826 .build());
3827 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3828 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3829 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3830 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3831 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3832 .build());
3833
3834 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3835 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3836 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3837
3838 // Move the swipe a bit
3839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3840 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3841 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3842 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3843 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3844 .build());
3845
3846 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3847
3848 // End the swipe
3849 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3850 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3851 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3852 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3853 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3854 .build());
3855 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3856 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3857 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3858 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3859 .build());
3860 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3861 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3862 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3863 .build());
3864
3865 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3866 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3867 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3868
3869 window->assertNoEvents();
3870}
3871
3872TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3874 sp<FakeWindowHandle> window =
3875 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3876 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003878
3879 // Start a three-finger touchpad swipe
3880 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3881 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3882 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3883 .build());
3884 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3885 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3886 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3887 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3888 .build());
3889 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3890 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3891 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3892 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3893 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3894 .build());
3895
3896 // Move the swipe a bit
3897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3898 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3899 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3900 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3901 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3902 .build());
3903
3904 // End the swipe
3905 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3907 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3908 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3909 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3910 .build());
3911 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3912 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3913 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3914 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3915 .build());
3916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3917 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3918 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3919 .build());
3920
3921 window->assertNoEvents();
3922}
3923
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003924/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003925 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3926 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003927 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003928 */
3929TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3931 sp<FakeWindowHandle> window =
3932 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3933 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003934 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003935
3936 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3938 .downTime(baseTime + 10)
3939 .eventTime(baseTime + 10)
3940 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3941 .build());
3942
3943 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3944
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003945 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003946 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003947
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003948 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003949
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003950 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3951 .downTime(baseTime + 10)
3952 .eventTime(baseTime + 30)
3953 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3954 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3955 .build());
3956
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003957 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3958
3959 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003960 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3961 .downTime(baseTime + 10)
3962 .eventTime(baseTime + 40)
3963 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3964 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3965 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003966
3967 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3968
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3970 .downTime(baseTime + 10)
3971 .eventTime(baseTime + 50)
3972 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3973 .build());
3974
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003975 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
3976
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003977 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3978 .downTime(baseTime + 60)
3979 .eventTime(baseTime + 60)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
3981 .build());
3982
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003983 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003984}
3985
3986/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003987 * Ensure the correct coordinate spaces are used by InputDispatcher.
3988 *
3989 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3990 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3991 * space.
3992 */
3993class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3994public:
3995 void SetUp() override {
3996 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003997 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003998 }
3999
4000 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4001 gui::DisplayInfo info;
4002 info.displayId = displayId;
4003 info.transform = transform;
4004 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004005 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004006 }
4007
4008 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4009 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004010 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004011 }
4012
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004013 void removeAllWindowsAndDisplays() {
4014 mDisplayInfos.clear();
4015 mWindowInfos.clear();
4016 }
4017
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004018 // Set up a test scenario where the display has a scaled projection and there are two windows
4019 // on the display.
4020 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4021 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4022 // respectively.
4023 ui::Transform displayTransform;
4024 displayTransform.set(2, 0, 0, 4);
4025 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4026
4027 std::shared_ptr<FakeApplicationHandle> application =
4028 std::make_shared<FakeApplicationHandle>();
4029
4030 // Add two windows to the display. Their frames are represented in the display space.
4031 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004032 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4033 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004034 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4035 addWindow(firstWindow);
4036
4037 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004038 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4039 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004040 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4041 addWindow(secondWindow);
4042 return {std::move(firstWindow), std::move(secondWindow)};
4043 }
4044
4045private:
4046 std::vector<gui::DisplayInfo> mDisplayInfos;
4047 std::vector<gui::WindowInfo> mWindowInfos;
4048};
4049
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004050TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004051 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4052 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004053 // selected so that if the hit test was performed with the point and the bounds being in
4054 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004055 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4056 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4057 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004058
4059 firstWindow->consumeMotionDown();
4060 secondWindow->assertNoEvents();
4061}
4062
4063// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4064// the event should be treated as being in the logical display space.
4065TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4066 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4067 // Send down to the first window. The point is represented in the logical display space. The
4068 // point is selected so that if the hit test was done in logical display space, then it would
4069 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004070 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004071 PointF{75 * 2, 55 * 4});
4072
4073 firstWindow->consumeMotionDown();
4074 secondWindow->assertNoEvents();
4075}
4076
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004077// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4078// event should be treated as being in the logical display space.
4079TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4080 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4081
4082 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4083 ui::Transform injectedEventTransform;
4084 injectedEventTransform.set(matrix);
4085 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4086 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4087
4088 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4089 .displayId(ADISPLAY_ID_DEFAULT)
4090 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004091 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004092 .x(untransformedPoint.x)
4093 .y(untransformedPoint.y))
4094 .build();
4095 event.transform(matrix);
4096
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004097 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004098 InputEventInjectionSync::WAIT_FOR_RESULT);
4099
4100 firstWindow->consumeMotionDown();
4101 secondWindow->assertNoEvents();
4102}
4103
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004104TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4105 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4106
4107 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004108 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4109 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4110 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004111
4112 firstWindow->assertNoEvents();
4113 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004114 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004115 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4116
4117 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4118 EXPECT_EQ(300, event->getRawX(0));
4119 EXPECT_EQ(880, event->getRawY(0));
4120
4121 // Ensure that the x and y values are in the window's coordinate space.
4122 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4123 // the logical display space. This will be the origin of the window space.
4124 EXPECT_EQ(100, event->getX(0));
4125 EXPECT_EQ(80, event->getY(0));
4126}
4127
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004128/** Ensure consistent behavior of InputDispatcher in all orientations. */
4129class InputDispatcherDisplayOrientationFixture
4130 : public InputDispatcherDisplayProjectionTest,
4131 public ::testing::WithParamInterface<ui::Rotation> {};
4132
4133// This test verifies the touchable region of a window for all rotations of the display by tapping
4134// in different locations on the display, specifically points close to the four corners of a
4135// window.
4136TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4137 constexpr static int32_t displayWidth = 400;
4138 constexpr static int32_t displayHeight = 800;
4139
4140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4141
4142 const auto rotation = GetParam();
4143
4144 // Set up the display with the specified rotation.
4145 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4146 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4147 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4148 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4149 logicalDisplayWidth, logicalDisplayHeight);
4150 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4151
4152 // Create a window with its bounds determined in the logical display.
4153 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4154 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4155 sp<FakeWindowHandle> window =
4156 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4157 window->setFrame(frameInDisplay, displayTransform);
4158 addWindow(window);
4159
4160 // The following points in logical display space should be inside the window.
4161 static const std::array<vec2, 4> insidePoints{
4162 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4163 for (const auto pointInsideWindow : insidePoints) {
4164 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4165 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4167 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4168 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004169 window->consumeMotionDown();
4170
Prabir Pradhan678438e2023-04-13 19:32:51 +00004171 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4172 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4173 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004174 window->consumeMotionUp();
4175 }
4176
4177 // The following points in logical display space should be outside the window.
4178 static const std::array<vec2, 5> outsidePoints{
4179 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4180 for (const auto pointOutsideWindow : outsidePoints) {
4181 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4182 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004183 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4184 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4185 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004186
Prabir Pradhan678438e2023-04-13 19:32:51 +00004187 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4188 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4189 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004190 }
4191 window->assertNoEvents();
4192}
4193
4194// Run the precision tests for all rotations.
4195INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4196 InputDispatcherDisplayOrientationFixture,
4197 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4198 ui::ROTATION_270),
4199 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4200 return ftl::enum_string(testParamInfo.param);
4201 });
4202
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004203using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4204 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004205
4206class TransferTouchFixture : public InputDispatcherTest,
4207 public ::testing::WithParamInterface<TransferFunction> {};
4208
4209TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004210 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004211
4212 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004213 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004214 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4215 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004216 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004217 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004218 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4219 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004220 sp<FakeWindowHandle> wallpaper =
4221 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4222 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004223 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004224 mDispatcher->onWindowInfosChanged(
4225 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004226
4227 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004228 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4229 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004230
Svet Ganov5d3bc372020-01-26 23:11:07 -08004231 // Only the first window should get the down event
4232 firstWindow->consumeMotionDown();
4233 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004234 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004235
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004236 // Transfer touch to the second window
4237 TransferFunction f = GetParam();
4238 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4239 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004240 // The first window gets cancel and the second gets down
4241 firstWindow->consumeMotionCancel();
4242 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004243 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244
4245 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004246 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4247 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004248 // The first window gets no events and the second gets up
4249 firstWindow->assertNoEvents();
4250 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004251 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004252}
4253
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004254/**
4255 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4256 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4257 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4258 * natural to the user.
4259 * In this test, we are sending a pointer to both spy window and first window. We then try to
4260 * transfer touch to the second window. The dispatcher should identify the first window as the
4261 * one that should lose the gesture, and therefore the action should be to move the gesture from
4262 * the first window to the second.
4263 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4264 * the other API, as well.
4265 */
4266TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4267 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4268
4269 // Create a couple of windows + a spy window
4270 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004271 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004272 spyWindow->setTrustedOverlay(true);
4273 spyWindow->setSpy(true);
4274 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004275 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004276 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004277 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004278
4279 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004280 mDispatcher->onWindowInfosChanged(
4281 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004282
4283 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004284 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4285 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004286 // Only the first window and spy should get the down event
4287 spyWindow->consumeMotionDown();
4288 firstWindow->consumeMotionDown();
4289
4290 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4291 // if f === 'transferTouch'.
4292 TransferFunction f = GetParam();
4293 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4294 ASSERT_TRUE(success);
4295 // The first window gets cancel and the second gets down
4296 firstWindow->consumeMotionCancel();
4297 secondWindow->consumeMotionDown();
4298
4299 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004300 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4301 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004302 // The first window gets no events and the second+spy get up
4303 firstWindow->assertNoEvents();
4304 spyWindow->consumeMotionUp();
4305 secondWindow->consumeMotionUp();
4306}
4307
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004308TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004309 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004310
4311 PointF touchPoint = {10, 10};
4312
4313 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004314 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004315 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4316 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004317 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004318 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004319 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4320 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004321 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004322
4323 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004324 mDispatcher->onWindowInfosChanged(
4325 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004326
4327 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004328 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4329 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4330 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004331 // Only the first window should get the down event
4332 firstWindow->consumeMotionDown();
4333 secondWindow->assertNoEvents();
4334
4335 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004336 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4337 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004338 // Only the first window should get the pointer down event
4339 firstWindow->consumeMotionPointerDown(1);
4340 secondWindow->assertNoEvents();
4341
4342 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004343 TransferFunction f = GetParam();
4344 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4345 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004346 // The first window gets cancel and the second gets down and pointer down
4347 firstWindow->consumeMotionCancel();
4348 secondWindow->consumeMotionDown();
4349 secondWindow->consumeMotionPointerDown(1);
4350
4351 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004352 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4353 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004354 // The first window gets nothing and the second gets pointer up
4355 firstWindow->assertNoEvents();
4356 secondWindow->consumeMotionPointerUp(1);
4357
4358 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004359 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4360 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004361 // The first window gets nothing and the second gets up
4362 firstWindow->assertNoEvents();
4363 secondWindow->consumeMotionUp();
4364}
4365
Arthur Hungc539dbb2022-12-08 07:45:36 +00004366TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4368
4369 // Create a couple of windows
4370 sp<FakeWindowHandle> firstWindow =
4371 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4372 ADISPLAY_ID_DEFAULT);
4373 firstWindow->setDupTouchToWallpaper(true);
4374 sp<FakeWindowHandle> secondWindow =
4375 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4376 ADISPLAY_ID_DEFAULT);
4377 secondWindow->setDupTouchToWallpaper(true);
4378
4379 sp<FakeWindowHandle> wallpaper1 =
4380 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4381 wallpaper1->setIsWallpaper(true);
4382
4383 sp<FakeWindowHandle> wallpaper2 =
4384 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4385 wallpaper2->setIsWallpaper(true);
4386 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004387 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4388 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4389 {},
4390 0,
4391 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004392
4393 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004394 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4395 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004396
4397 // Only the first window should get the down event
4398 firstWindow->consumeMotionDown();
4399 secondWindow->assertNoEvents();
4400 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4401 wallpaper2->assertNoEvents();
4402
4403 // Transfer touch focus to the second window
4404 TransferFunction f = GetParam();
4405 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4406 ASSERT_TRUE(success);
4407
4408 // The first window gets cancel and the second gets down
4409 firstWindow->consumeMotionCancel();
4410 secondWindow->consumeMotionDown();
4411 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4412 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4413
4414 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004415 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4416 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004417 // The first window gets no events and the second gets up
4418 firstWindow->assertNoEvents();
4419 secondWindow->consumeMotionUp();
4420 wallpaper1->assertNoEvents();
4421 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4422}
4423
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004424// For the cases of single pointer touch and two pointers non-split touch, the api's
4425// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4426// for the case where there are multiple pointers split across several windows.
4427INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4428 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004429 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4430 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004431 return dispatcher->transferTouch(destChannelToken,
4432 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004433 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004434 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4435 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004436 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004437 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004438 }));
4439
Svet Ganov5d3bc372020-01-26 23:11:07 -08004440TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004441 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004442
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004443 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004444 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4445 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004446 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004447
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004448 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004449 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4450 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004451 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004452
4453 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004454 mDispatcher->onWindowInfosChanged(
4455 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004456
4457 PointF pointInFirst = {300, 200};
4458 PointF pointInSecond = {300, 600};
4459
4460 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004461 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4462 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4463 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004464 // Only the first window should get the down event
4465 firstWindow->consumeMotionDown();
4466 secondWindow->assertNoEvents();
4467
4468 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004469 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4470 ADISPLAY_ID_DEFAULT,
4471 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004472 // The first window gets a move and the second a down
4473 firstWindow->consumeMotionMove();
4474 secondWindow->consumeMotionDown();
4475
4476 // Transfer touch focus to the second window
4477 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4478 // The first window gets cancel and the new gets pointer down (it already saw down)
4479 firstWindow->consumeMotionCancel();
4480 secondWindow->consumeMotionPointerDown(1);
4481
4482 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004483 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4484 ADISPLAY_ID_DEFAULT,
4485 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004486 // The first window gets nothing and the second gets pointer up
4487 firstWindow->assertNoEvents();
4488 secondWindow->consumeMotionPointerUp(1);
4489
4490 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004491 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4492 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004493 // The first window gets nothing and the second gets up
4494 firstWindow->assertNoEvents();
4495 secondWindow->consumeMotionUp();
4496}
4497
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004498// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4499// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4500// touch is not supported, so the touch should continue on those windows and the transferred-to
4501// window should get nothing.
4502TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4504
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004505 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004506 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4507 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004508 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004509
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004510 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004511 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4512 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004513 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004514
4515 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004516 mDispatcher->onWindowInfosChanged(
4517 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004518
4519 PointF pointInFirst = {300, 200};
4520 PointF pointInSecond = {300, 600};
4521
4522 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004523 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4524 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4525 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004526 // Only the first window should get the down event
4527 firstWindow->consumeMotionDown();
4528 secondWindow->assertNoEvents();
4529
4530 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004531 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4532 ADISPLAY_ID_DEFAULT,
4533 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004534 // The first window gets a move and the second a down
4535 firstWindow->consumeMotionMove();
4536 secondWindow->consumeMotionDown();
4537
4538 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004539 const bool transferred =
4540 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004541 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4542 ASSERT_FALSE(transferred);
4543 firstWindow->assertNoEvents();
4544 secondWindow->assertNoEvents();
4545
4546 // The rest of the dispatch should proceed as normal
4547 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004548 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4549 ADISPLAY_ID_DEFAULT,
4550 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004551 // The first window gets MOVE and the second gets pointer up
4552 firstWindow->consumeMotionMove();
4553 secondWindow->consumeMotionUp();
4554
4555 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4557 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004558 // The first window gets nothing and the second gets up
4559 firstWindow->consumeMotionUp();
4560 secondWindow->assertNoEvents();
4561}
4562
Arthur Hungabbb9d82021-09-01 14:52:30 +00004563// This case will create two windows and one mirrored window on the default display and mirror
4564// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4565// the windows info of second display before default display.
4566TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4568 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004569 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004570 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004571 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004572 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004573 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004574
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004575 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004576 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004577
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004578 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004579 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004580
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004581 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583
4584 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004585 mDispatcher->onWindowInfosChanged(
4586 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4587 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4588 *secondWindowInPrimary->getInfo()},
4589 {},
4590 0,
4591 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004592
4593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004594 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004595 {50, 50}))
4596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4597
4598 // Window should receive motion event.
4599 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4600
4601 // Transfer touch focus
4602 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4603 secondWindowInPrimary->getToken()));
4604 // The first window gets cancel.
4605 firstWindowInPrimary->consumeMotionCancel();
4606 secondWindowInPrimary->consumeMotionDown();
4607
4608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004609 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004610 ADISPLAY_ID_DEFAULT, {150, 50}))
4611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4612 firstWindowInPrimary->assertNoEvents();
4613 secondWindowInPrimary->consumeMotionMove();
4614
4615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004616 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004617 {150, 50}))
4618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4619 firstWindowInPrimary->assertNoEvents();
4620 secondWindowInPrimary->consumeMotionUp();
4621}
4622
4623// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4624// 'transferTouch' api.
4625TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4627 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004628 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004629 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004630 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004631 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004632 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004633
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004634 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004635 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004636
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004637 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004638 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004639
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004640 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004641 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642
4643 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004644 mDispatcher->onWindowInfosChanged(
4645 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4646 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4647 *secondWindowInPrimary->getInfo()},
4648 {},
4649 0,
4650 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004651
4652 // Touch on second display.
4653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004654 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
4655 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00004656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4657
4658 // Window should receive motion event.
4659 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4660
4661 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004662 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004663
4664 // The first window gets cancel.
4665 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4666 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4667
4668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004669 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004670 SECOND_DISPLAY_ID, {150, 50}))
4671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4672 firstWindowInPrimary->assertNoEvents();
4673 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4674
4675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004676 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00004677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4678 firstWindowInPrimary->assertNoEvents();
4679 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4680}
4681
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004682TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004684 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4685 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004686
Vishnu Nair47074b82020-08-14 11:54:47 -07004687 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004688 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004689 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004690
4691 window->consumeFocusEvent(true);
4692
Prabir Pradhan678438e2023-04-13 19:32:51 +00004693 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004694
4695 // Window should receive key down event.
4696 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004697
4698 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004699 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004700 mFakePolicy->assertUserActivityPoked();
4701}
4702
4703TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4706 "Fake Window", ADISPLAY_ID_DEFAULT);
4707
4708 window->setDisableUserActivity(true);
4709 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004711 setFocusedWindow(window);
4712
4713 window->consumeFocusEvent(true);
4714
4715 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4716
4717 // Window should receive key down event.
4718 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4719
4720 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004721 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004722 mFakePolicy->assertUserActivityNotPoked();
4723}
4724
4725TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4727 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4728 "Fake Window", ADISPLAY_ID_DEFAULT);
4729
4730 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004731 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004732 setFocusedWindow(window);
4733
4734 window->consumeFocusEvent(true);
4735
4736 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4737 mDispatcher->waitForIdle();
4738
4739 // System key is not passed down
4740 window->assertNoEvents();
4741
4742 // Should have poked user activity
4743 mFakePolicy->assertUserActivityPoked();
4744}
4745
4746TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4749 "Fake Window", ADISPLAY_ID_DEFAULT);
4750
4751 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004753 setFocusedWindow(window);
4754
4755 window->consumeFocusEvent(true);
4756
4757 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4758 mDispatcher->waitForIdle();
4759
4760 // System key is not passed down
4761 window->assertNoEvents();
4762
4763 // Should have poked user activity
4764 mFakePolicy->assertUserActivityPoked();
4765}
4766
4767TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4769 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4770 "Fake Window", ADISPLAY_ID_DEFAULT);
4771
4772 window->setDisableUserActivity(true);
4773 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004774 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004775 setFocusedWindow(window);
4776
4777 window->consumeFocusEvent(true);
4778
4779 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4780 mDispatcher->waitForIdle();
4781
4782 // System key is not passed down
4783 window->assertNoEvents();
4784
4785 // Should have poked user activity
4786 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004787}
4788
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004789TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4790 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4791 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4792 "Fake Window", ADISPLAY_ID_DEFAULT);
4793
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004794 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004795
4796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004797 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004798 ADISPLAY_ID_DEFAULT, {100, 100}))
4799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4800
4801 window->consumeMotionEvent(
4802 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4803
4804 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004805 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004806 mFakePolicy->assertUserActivityPoked();
4807}
4808
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004809TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4812 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004814 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004815
Prabir Pradhan678438e2023-04-13 19:32:51 +00004816 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004817 mDispatcher->waitForIdle();
4818
4819 window->assertNoEvents();
4820}
4821
4822// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4823TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004824 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004825 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4826 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004827
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004828 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004829
4830 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004831 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004832 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004833 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4834 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004835
4836 // Window should receive only the motion event
4837 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4838 window->assertNoEvents(); // Key event or focus event will not be received
4839}
4840
arthurhungea3f4fc2020-12-21 23:18:53 +08004841TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4842 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4843
arthurhungea3f4fc2020-12-21 23:18:53 +08004844 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004845 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4846 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004847 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004848
arthurhungea3f4fc2020-12-21 23:18:53 +08004849 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004850 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4851 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004852 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004853
4854 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004855 mDispatcher->onWindowInfosChanged(
4856 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08004857
4858 PointF pointInFirst = {300, 200};
4859 PointF pointInSecond = {300, 600};
4860
4861 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004862 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4863 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4864 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004865 // Only the first window should get the down event
4866 firstWindow->consumeMotionDown();
4867 secondWindow->assertNoEvents();
4868
4869 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004870 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4871 ADISPLAY_ID_DEFAULT,
4872 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004873 // The first window gets a move and the second a down
4874 firstWindow->consumeMotionMove();
4875 secondWindow->consumeMotionDown();
4876
4877 // Send pointer cancel to the second window
4878 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004879 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004880 {pointInFirst, pointInSecond});
4881 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004882 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004883 // The first window gets move and the second gets cancel.
4884 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4885 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4886
4887 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004888 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4889 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004890 // The first window gets up and the second gets nothing.
4891 firstWindow->consumeMotionUp();
4892 secondWindow->assertNoEvents();
4893}
4894
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004895TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4897
4898 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004899 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004900 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004901 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4902 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4903 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4904
Harry Cutts33476232023-01-30 19:57:29 +00004905 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004906 window->assertNoEvents();
4907 mDispatcher->waitForIdle();
4908}
4909
chaviwd1c23182019-12-20 18:44:56 -08004910class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004911public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004912 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004913 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004914 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004915 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004916 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004917 }
4918
chaviwd1c23182019-12-20 18:44:56 -08004919 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4920
4921 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004922 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4923 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004924 }
4925
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004926 std::optional<int32_t> receiveEvent() {
4927 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
4928 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004929
4930 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4931
chaviwd1c23182019-12-20 18:44:56 -08004932 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004933 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004934 expectedDisplayId, expectedFlags);
4935 }
4936
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004937 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004938 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004939 expectedDisplayId, expectedFlags);
4940 }
4941
chaviwd1c23182019-12-20 18:44:56 -08004942 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004943 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004944 expectedDisplayId, expectedFlags);
4945 }
4946
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004947 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004948 mInputReceiver->consumeMotionEvent(
4949 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4950 WithDisplayId(expectedDisplayId),
4951 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004952 }
4953
Arthur Hungfbfa5722021-11-16 02:45:54 +00004954 void consumeMotionPointerDown(int32_t pointerIdx) {
4955 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4956 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004957 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004958 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004959 }
4960
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004961 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
Evan Rosky84f07f02021-04-16 10:42:42 -07004962
chaviwd1c23182019-12-20 18:44:56 -08004963 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4964
4965private:
4966 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004967};
4968
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004969using InputDispatcherMonitorTest = InputDispatcherTest;
4970
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004971/**
4972 * Two entities that receive touch: A window, and a global monitor.
4973 * The touch goes to the window, and then the window disappears.
4974 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4975 * for the monitor, as well.
4976 * 1. foregroundWindow
4977 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4978 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004979TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4981 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004982 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004983
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004984 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004985
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004986 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004988 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004989 {100, 200}))
4990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4991
4992 // Both the foreground window and the global monitor should receive the touch down
4993 window->consumeMotionDown();
4994 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4995
4996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004997 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004998 ADISPLAY_ID_DEFAULT, {110, 200}))
4999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5000
5001 window->consumeMotionMove();
5002 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5003
5004 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005005 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005006 window->consumeMotionCancel();
5007 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5008
5009 // If more events come in, there will be no more foreground window to send them to. This will
5010 // cause a cancel for the monitor, as well.
5011 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005012 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005013 ADISPLAY_ID_DEFAULT, {120, 200}))
5014 << "Injection should fail because the window was removed";
5015 window->assertNoEvents();
5016 // Global monitor now gets the cancel
5017 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5018}
5019
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005020TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005021 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005022 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5023 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005024 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005025
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005026 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005027
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005029 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005030 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005031 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005032 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005033}
5034
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005035TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5036 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005037
Chris Yea209fde2020-07-22 13:54:51 -07005038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005039 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5040 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005041 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005044 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005045 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005046 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005047 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005048
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005049 // Pilfer pointers from the monitor.
5050 // This should not do anything and the window should continue to receive events.
5051 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005052
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005054 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005055 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005057
5058 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5059 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005060}
5061
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005062TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005063 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005064 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5065 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005066 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005067 window->setWindowOffset(20, 40);
5068 window->setWindowTransform(0, 1, -1, 0);
5069
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005070 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005071
5072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005073 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5075 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5076 MotionEvent* event = monitor.consumeMotion();
5077 // Even though window has transform, gesture monitor must not.
5078 ASSERT_EQ(ui::Transform(), event->getTransform());
5079}
5080
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005081TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005083 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005084
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005085 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005086 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005087 << "Injection should fail if there is a monitor, but no touchable window";
5088 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005089}
5090
chaviw81e2bb92019-12-18 15:03:51 -08005091TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005093 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5094 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005097
5098 NotifyMotionArgs motionArgs =
5099 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5100 ADISPLAY_ID_DEFAULT);
5101
Prabir Pradhan678438e2023-04-13 19:32:51 +00005102 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005103 // Window should receive motion down event.
5104 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5105
5106 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005107 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005108 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5109 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5110 motionArgs.pointerCoords[0].getX() - 10);
5111
Prabir Pradhan678438e2023-04-13 19:32:51 +00005112 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005113 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005114 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005115}
5116
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005117/**
5118 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5119 * the device default right away. In the test scenario, we check both the default value,
5120 * and the action of enabling / disabling.
5121 */
5122TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005123 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005124 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5125 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005126 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005127
5128 // Set focused application.
5129 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005130 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005131
5132 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005133 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005134 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005135 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005136
5137 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005138 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005139 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005140 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005141
5142 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005143 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005144 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005145 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005146 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005147 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005148 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005149 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005150
5151 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005152 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005153 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005154 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005155
5156 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005157 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005158 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005159 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005160 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005161 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005162 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005163 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005164
5165 window->assertNoEvents();
5166}
5167
Gang Wange9087892020-01-07 12:17:14 -05005168TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005170 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5171 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005172
5173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005174 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005175
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005177 setFocusedWindow(window);
5178
Harry Cutts33476232023-01-30 19:57:29 +00005179 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005180
Prabir Pradhan678438e2023-04-13 19:32:51 +00005181 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5182 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005183
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005184 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005185 ASSERT_NE(event, nullptr);
5186
5187 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5188 ASSERT_NE(verified, nullptr);
5189 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5190
5191 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5192 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5193 ASSERT_EQ(keyArgs.source, verified->source);
5194 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5195
5196 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5197
5198 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005199 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005200 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005201 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5202 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5203 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5204 ASSERT_EQ(0, verifiedKey.repeatCount);
5205}
5206
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005207TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005209 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5210 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005211
5212 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5213
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005214 ui::Transform transform;
5215 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5216
5217 gui::DisplayInfo displayInfo;
5218 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5219 displayInfo.transform = transform;
5220
Patrick Williamsd828f302023-04-28 17:52:08 -05005221 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005222
Prabir Pradhan678438e2023-04-13 19:32:51 +00005223 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005224 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5225 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005226 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005227
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005228 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005229 ASSERT_NE(event, nullptr);
5230
5231 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5232 ASSERT_NE(verified, nullptr);
5233 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5234
5235 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5236 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5237 EXPECT_EQ(motionArgs.source, verified->source);
5238 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5239
5240 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5241
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005242 const vec2 rawXY =
5243 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5244 motionArgs.pointerCoords[0].getXYValue());
5245 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5246 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005247 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005248 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005249 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005250 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5251 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5252}
5253
chaviw09c8d2d2020-08-24 15:48:26 -07005254/**
5255 * Ensure that separate calls to sign the same data are generating the same key.
5256 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5257 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5258 * tests.
5259 */
5260TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5261 KeyEvent event = getTestKeyEvent();
5262 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5263
5264 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5265 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5266 ASSERT_EQ(hmac1, hmac2);
5267}
5268
5269/**
5270 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5271 */
5272TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5273 KeyEvent event = getTestKeyEvent();
5274 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5275 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5276
5277 verifiedEvent.deviceId += 1;
5278 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5279
5280 verifiedEvent.source += 1;
5281 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5282
5283 verifiedEvent.eventTimeNanos += 1;
5284 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5285
5286 verifiedEvent.displayId += 1;
5287 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5288
5289 verifiedEvent.action += 1;
5290 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5291
5292 verifiedEvent.downTimeNanos += 1;
5293 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5294
5295 verifiedEvent.flags += 1;
5296 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5297
5298 verifiedEvent.keyCode += 1;
5299 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5300
5301 verifiedEvent.scanCode += 1;
5302 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5303
5304 verifiedEvent.metaState += 1;
5305 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5306
5307 verifiedEvent.repeatCount += 1;
5308 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5309}
5310
Vishnu Nair958da932020-08-21 17:12:37 -07005311TEST_F(InputDispatcherTest, SetFocusedWindow) {
5312 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5313 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005314 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005315 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005316 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005317 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5318
5319 // Top window is also focusable but is not granted focus.
5320 windowTop->setFocusable(true);
5321 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005322 mDispatcher->onWindowInfosChanged(
5323 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005324 setFocusedWindow(windowSecond);
5325
5326 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005328 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005329
5330 // Focused window should receive event.
5331 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5332 windowTop->assertNoEvents();
5333}
5334
5335TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5336 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5337 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005338 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005339 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5340
5341 window->setFocusable(true);
5342 // Release channel for window is no longer valid.
5343 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005344 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005345 setFocusedWindow(window);
5346
5347 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005348 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005349
5350 // window channel is invalid, so it should not receive any input event.
5351 window->assertNoEvents();
5352}
5353
5354TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5355 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5356 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005357 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005358 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005359 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5360
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005361 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005362 setFocusedWindow(window);
5363
5364 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005365 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005366
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005367 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005368 window->assertNoEvents();
5369}
5370
5371TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5373 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005374 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005375 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005376 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005377 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5378
5379 windowTop->setFocusable(true);
5380 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005381 mDispatcher->onWindowInfosChanged(
5382 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005383 setFocusedWindow(windowTop);
5384 windowTop->consumeFocusEvent(true);
5385
Chavi Weingarten847e8512023-03-29 00:26:09 +00005386 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005387 mDispatcher->onWindowInfosChanged(
5388 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005389 windowSecond->consumeFocusEvent(true);
5390 windowTop->consumeFocusEvent(false);
5391
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005393 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005394
5395 // Focused window should receive event.
5396 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5397}
5398
Chavi Weingarten847e8512023-03-29 00:26:09 +00005399TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5401 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005402 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005403 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005404 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005405 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5406
5407 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005408 windowSecond->setFocusable(false);
5409 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005410 mDispatcher->onWindowInfosChanged(
5411 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005412 setFocusedWindow(windowTop);
5413 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005414
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005416 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005417
5418 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005419 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005420 windowSecond->assertNoEvents();
5421}
5422
5423TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5425 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005426 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005427 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005428 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5429 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005430 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5431
5432 window->setFocusable(true);
5433 previousFocusedWindow->setFocusable(true);
5434 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005435 mDispatcher->onWindowInfosChanged(
5436 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005437 setFocusedWindow(previousFocusedWindow);
5438 previousFocusedWindow->consumeFocusEvent(true);
5439
5440 // Requesting focus on invisible window takes focus from currently focused window.
5441 setFocusedWindow(window);
5442 previousFocusedWindow->consumeFocusEvent(false);
5443
5444 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005446 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5447 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005448
5449 // Window does not get focus event or key down.
5450 window->assertNoEvents();
5451
5452 // Window becomes visible.
5453 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005454 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005455
5456 // Window receives focus event.
5457 window->consumeFocusEvent(true);
5458 // Focused window receives key down.
5459 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5460}
5461
Vishnu Nair599f1412021-06-21 10:39:58 -07005462TEST_F(InputDispatcherTest, DisplayRemoved) {
5463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5464 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005465 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005466 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5467
5468 // window is granted focus.
5469 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005470 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005471 setFocusedWindow(window);
5472 window->consumeFocusEvent(true);
5473
5474 // When a display is removed window loses focus.
5475 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5476 window->consumeFocusEvent(false);
5477}
5478
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005479/**
5480 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5481 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5482 * of the 'slipperyEnterWindow'.
5483 *
5484 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5485 * a way so that the touched location is no longer covered by the top window.
5486 *
5487 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5488 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5489 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5490 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5491 * with ACTION_DOWN).
5492 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5493 * window moved itself away from the touched location and had Flag::SLIPPERY.
5494 *
5495 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5496 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5497 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5498 *
5499 * In this test, we ensure that the event received by the bottom window has
5500 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5501 */
5502TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005503 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005504 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005505
5506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5507 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5508
5509 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005510 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005511 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005512 // Make sure this one overlaps the bottom window
5513 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5514 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5515 // one. Windows with the same owner are not considered to be occluding each other.
5516 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5517
5518 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005519 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005520 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5521
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005522 mDispatcher->onWindowInfosChanged(
5523 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005524
5525 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5528 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005529 slipperyExitWindow->consumeMotionDown();
5530 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005531 mDispatcher->onWindowInfosChanged(
5532 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005533
Prabir Pradhan678438e2023-04-13 19:32:51 +00005534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5536 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005537
5538 slipperyExitWindow->consumeMotionCancel();
5539
5540 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5541 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5542}
5543
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005544/**
5545 * Two windows, one on the left and another on the right. The left window is slippery. The right
5546 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5547 * touch moves from the left window into the right window, the gesture should continue to go to the
5548 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5549 * reproduces a crash.
5550 */
5551TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5553
5554 sp<FakeWindowHandle> leftSlipperyWindow =
5555 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5556 leftSlipperyWindow->setSlippery(true);
5557 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5558
5559 sp<FakeWindowHandle> rightDropTouchesWindow =
5560 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5561 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5562 rightDropTouchesWindow->setDropInput(true);
5563
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005564 mDispatcher->onWindowInfosChanged(
5565 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005566
5567 // Start touch in the left window
5568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5569 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5570 .build());
5571 leftSlipperyWindow->consumeMotionDown();
5572
5573 // And move it into the right window
5574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5575 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5576 .build());
5577
5578 // Since the right window isn't eligible to receive input, touch does not slip.
5579 // The left window continues to receive the gesture.
5580 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5581 rightDropTouchesWindow->assertNoEvents();
5582}
5583
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005584TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005585 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5587
5588 sp<FakeWindowHandle> leftWindow =
5589 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5590 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005591 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005592
5593 sp<FakeWindowHandle> rightSpy =
5594 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5595 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005596 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005597 rightSpy->setSpy(true);
5598 rightSpy->setTrustedOverlay(true);
5599
5600 sp<FakeWindowHandle> rightWindow =
5601 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5602 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005603 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005605 mDispatcher->onWindowInfosChanged(
5606 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005607
5608 // Touch in the left window
5609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5610 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5611 .build());
5612 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5613 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005614 ASSERT_NO_FATAL_FAILURE(
5615 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005616
5617 // Touch another finger over the right windows
5618 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5619 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5620 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5621 .build());
5622 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5623 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5624 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5625 mDispatcher->waitForIdle();
5626 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005627 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5628 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005629
5630 // Release finger over left window. The UP actions are not treated as device interaction.
5631 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5632 // is part of the UP action, we do not treat this as device interaction.
5633 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5634 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5635 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5636 .build());
5637 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5638 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5639 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5640 mDispatcher->waitForIdle();
5641 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5642
5643 // Move remaining finger
5644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5645 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5646 .build());
5647 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5648 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5649 mDispatcher->waitForIdle();
5650 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005651 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005652
5653 // Release all fingers
5654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5655 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5656 .build());
5657 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5658 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5659 mDispatcher->waitForIdle();
5660 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5661}
5662
5663TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5665
5666 sp<FakeWindowHandle> window =
5667 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5668 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005669 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005670
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005672 setFocusedWindow(window);
5673 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5674
5675 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5676 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5677 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005678 ASSERT_NO_FATAL_FAILURE(
5679 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005680
5681 // The UP actions are not treated as device interaction.
5682 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5683 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5684 mDispatcher->waitForIdle();
5685 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5686}
5687
Garfield Tan1c7bc862020-01-28 13:24:04 -08005688class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5689protected:
5690 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5691 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5692
Chris Yea209fde2020-07-22 13:54:51 -07005693 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005694 sp<FakeWindowHandle> mWindow;
5695
5696 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005697 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005698 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005699 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005700 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005701 ASSERT_EQ(OK, mDispatcher->start());
5702
5703 setUpWindow();
5704 }
5705
5706 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005707 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005708 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005709
Vishnu Nair47074b82020-08-14 11:54:47 -07005710 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005711 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005712 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005713 mWindow->consumeFocusEvent(true);
5714 }
5715
Chris Ye2ad95392020-09-01 13:44:44 -07005716 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005717 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005718 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005719 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005720 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005721
5722 // Window should receive key down event.
5723 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5724 }
5725
5726 void expectKeyRepeatOnce(int32_t repeatCount) {
5727 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005728 mWindow->consumeKeyEvent(
5729 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08005730 }
5731
Chris Ye2ad95392020-09-01 13:44:44 -07005732 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005733 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005734 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005735 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005736 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005737
5738 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005739 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005740 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005741 }
5742};
5743
5744TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005745 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005746 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5747 expectKeyRepeatOnce(repeatCount);
5748 }
5749}
5750
5751TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005752 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005753 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5754 expectKeyRepeatOnce(repeatCount);
5755 }
Harry Cutts33476232023-01-30 19:57:29 +00005756 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005757 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005758 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5759 expectKeyRepeatOnce(repeatCount);
5760 }
5761}
5762
5763TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005764 sendAndConsumeKeyDown(/*deviceId=*/1);
5765 expectKeyRepeatOnce(/*repeatCount=*/1);
5766 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005767 mWindow->assertNoEvents();
5768}
5769
5770TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005771 sendAndConsumeKeyDown(/*deviceId=*/1);
5772 expectKeyRepeatOnce(/*repeatCount=*/1);
5773 sendAndConsumeKeyDown(/*deviceId=*/2);
5774 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005775 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005776 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005777 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005778 expectKeyRepeatOnce(/*repeatCount=*/2);
5779 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005780 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005781 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005782 mWindow->assertNoEvents();
5783}
5784
5785TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005786 sendAndConsumeKeyDown(/*deviceId=*/1);
5787 expectKeyRepeatOnce(/*repeatCount=*/1);
5788 sendAndConsumeKeyDown(/*deviceId=*/2);
5789 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005790 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005791 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005792 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005793 mWindow->assertNoEvents();
5794}
5795
liushenxiang42232912021-05-21 20:24:09 +08005796TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5797 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005798 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005799 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005800 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5801 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5802 mWindow->assertNoEvents();
5803}
5804
Garfield Tan1c7bc862020-01-28 13:24:04 -08005805TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005806 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005807 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005808 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005809 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005810 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5811 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5812 IdGenerator::getSource(repeatEvent->getId()));
5813 }
5814}
5815
5816TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005817 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005818 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005819
5820 std::unordered_set<int32_t> idSet;
5821 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005822 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005823 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5824 int32_t id = repeatEvent->getId();
5825 EXPECT_EQ(idSet.end(), idSet.find(id));
5826 idSet.insert(id);
5827 }
5828}
5829
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005830/* Test InputDispatcher for MultiDisplay */
5831class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5832public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005833 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005834 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005835
Chris Yea209fde2020-07-22 13:54:51 -07005836 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005837 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005838 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005839
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005840 // Set focus window for primary display, but focused display would be second one.
5841 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005842 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005843 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
5844
Vishnu Nair958da932020-08-21 17:12:37 -07005845 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005846 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005847
Chris Yea209fde2020-07-22 13:54:51 -07005848 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005849 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005850 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005851 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005852 // Set focus display to second one.
5853 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5854 // Set focus window for second display.
5855 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005856 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005857 mDispatcher->onWindowInfosChanged(
5858 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005859 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005860 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005861 }
5862
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005863 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005864 InputDispatcherTest::TearDown();
5865
Chris Yea209fde2020-07-22 13:54:51 -07005866 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005867 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005868 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005869 windowInSecondary.clear();
5870 }
5871
5872protected:
Chris Yea209fde2020-07-22 13:54:51 -07005873 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005874 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005875 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005876 sp<FakeWindowHandle> windowInSecondary;
5877};
5878
5879TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5880 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005882 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005884 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005885 windowInSecondary->assertNoEvents();
5886
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005887 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005889 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005891 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005892 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005893}
5894
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005895TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005896 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005898 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005899 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005900 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005901 windowInSecondary->assertNoEvents();
5902
5903 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005905 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005906 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005907 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005908
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005909 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005910 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08005911
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005912 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005913 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005914 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005915
5916 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005917 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08005918 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005919 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005920 windowInSecondary->assertNoEvents();
5921}
5922
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005923// Test per-display input monitors for motion event.
5924TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005925 FakeMonitorReceiver monitorInPrimary =
5926 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5927 FakeMonitorReceiver monitorInSecondary =
5928 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005929
5930 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005932 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005933 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005934 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005935 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005936 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005937 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005938
5939 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005941 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005943 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005944 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005945 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005946 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005947
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005948 // Lift up the touch from the second display
5949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005950 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5952 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5953 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5954
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005955 // Test inject a non-pointer motion event.
5956 // If specific a display, it will dispatch to the focused window of particular display,
5957 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005959 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005961 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005962 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005963 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005964 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005965}
5966
5967// Test per-display input monitors for key event.
5968TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005969 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005970 FakeMonitorReceiver monitorInPrimary =
5971 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5972 FakeMonitorReceiver monitorInSecondary =
5973 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005974
5975 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005977 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005978 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005979 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005980 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005981 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005982}
5983
Vishnu Nair958da932020-08-21 17:12:37 -07005984TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5985 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005986 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005987 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005988 mDispatcher->onWindowInfosChanged(
5989 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
5990 *windowInSecondary->getInfo()},
5991 {},
5992 0,
5993 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005994 setFocusedWindow(secondWindowInPrimary);
5995 windowInPrimary->consumeFocusEvent(false);
5996 secondWindowInPrimary->consumeFocusEvent(true);
5997
5998 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6000 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006001 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006002 windowInPrimary->assertNoEvents();
6003 windowInSecondary->assertNoEvents();
6004 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6005}
6006
Arthur Hungdfd528e2021-12-08 13:23:04 +00006007TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6008 FakeMonitorReceiver monitorInPrimary =
6009 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6010 FakeMonitorReceiver monitorInSecondary =
6011 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6012
6013 // Test touch down on primary display.
6014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006015 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6017 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6018 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6019
6020 // Test touch down on second display.
6021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006022 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6024 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6025 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6026
6027 // Trigger cancel touch.
6028 mDispatcher->cancelCurrentTouch();
6029 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6030 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6031 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6032 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6033
6034 // Test inject a move motion event, no window/monitor should receive the event.
6035 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006036 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006037 ADISPLAY_ID_DEFAULT, {110, 200}))
6038 << "Inject motion event should return InputEventInjectionResult::FAILED";
6039 windowInPrimary->assertNoEvents();
6040 monitorInPrimary.assertNoEvents();
6041
6042 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006043 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006044 SECOND_DISPLAY_ID, {110, 200}))
6045 << "Inject motion event should return InputEventInjectionResult::FAILED";
6046 windowInSecondary->assertNoEvents();
6047 monitorInSecondary.assertNoEvents();
6048}
6049
Jackal Guof9696682018-10-05 12:23:23 +08006050class InputFilterTest : public InputDispatcherTest {
6051protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006052 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6053 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006054 NotifyMotionArgs motionArgs;
6055
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006056 motionArgs =
6057 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006058 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006059 motionArgs =
6060 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006061 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006062 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006063 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006064 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006065 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006066 } else {
6067 mFakePolicy->assertFilterInputEventWasNotCalled();
6068 }
6069 }
6070
6071 void testNotifyKey(bool expectToBeFiltered) {
6072 NotifyKeyArgs keyArgs;
6073
6074 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006075 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006076 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006077 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006078 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006079
6080 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006081 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006082 } else {
6083 mFakePolicy->assertFilterInputEventWasNotCalled();
6084 }
6085 }
6086};
6087
6088// Test InputFilter for MotionEvent
6089TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6090 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006091 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6092 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006093
6094 // Enable InputFilter
6095 mDispatcher->setInputFilterEnabled(true);
6096 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006097 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6098 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006099
6100 // Disable InputFilter
6101 mDispatcher->setInputFilterEnabled(false);
6102 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006103 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6104 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006105}
6106
6107// Test InputFilter for KeyEvent
6108TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6109 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006110 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006111
6112 // Enable InputFilter
6113 mDispatcher->setInputFilterEnabled(true);
6114 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006115 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006116
6117 // Disable InputFilter
6118 mDispatcher->setInputFilterEnabled(false);
6119 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006120 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006121}
6122
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006123// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6124// logical display coordinate space.
6125TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6126 ui::Transform firstDisplayTransform;
6127 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6128 ui::Transform secondDisplayTransform;
6129 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6130
6131 std::vector<gui::DisplayInfo> displayInfos(2);
6132 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6133 displayInfos[0].transform = firstDisplayTransform;
6134 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6135 displayInfos[1].transform = secondDisplayTransform;
6136
Patrick Williamsd828f302023-04-28 17:52:08 -05006137 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006138
6139 // Enable InputFilter
6140 mDispatcher->setInputFilterEnabled(true);
6141
6142 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006143 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6144 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006145}
6146
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006147class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6148protected:
6149 virtual void SetUp() override {
6150 InputDispatcherTest::SetUp();
6151
6152 /**
6153 * We don't need to enable input filter to test the injected event policy, but we enabled it
6154 * here to make the tests more realistic, since this policy only matters when inputfilter is
6155 * on.
6156 */
6157 mDispatcher->setInputFilterEnabled(true);
6158
6159 std::shared_ptr<InputApplicationHandle> application =
6160 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006161 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6162 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006163
6164 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6165 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006166 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006167 setFocusedWindow(mWindow);
6168 mWindow->consumeFocusEvent(true);
6169 }
6170
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006171 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6172 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006173 KeyEvent event;
6174
6175 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6176 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6177 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006178 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006179 const int32_t additionalPolicyFlags =
6180 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006182 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006183 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006184 policyFlags | additionalPolicyFlags));
6185
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006186 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006187 }
6188
6189 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6190 int32_t flags) {
6191 MotionEvent event;
6192 PointerProperties pointerProperties[1];
6193 PointerCoords pointerCoords[1];
6194 pointerProperties[0].clear();
6195 pointerProperties[0].id = 0;
6196 pointerCoords[0].clear();
6197 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6198 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6199
6200 ui::Transform identityTransform;
6201 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6202 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6203 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6204 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6205 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006206 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006207 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006208 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006209
6210 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006212 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006213 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006214 policyFlags | additionalPolicyFlags));
6215
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006216 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006217 }
6218
6219private:
6220 sp<FakeWindowHandle> mWindow;
6221};
6222
6223TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006224 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6225 // filter. Without it, the event will no different from a regularly injected event, and the
6226 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006227 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6228 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006229}
6230
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006231TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006232 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006233 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006234 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6235}
6236
6237TEST_F(InputFilterInjectionPolicyTest,
6238 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6239 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006240 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006241 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006242}
6243
6244TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006245 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6246 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006247}
6248
chaviwfd6d3512019-03-25 13:23:49 -07006249class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006250 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006251 InputDispatcherTest::SetUp();
6252
Chris Yea209fde2020-07-22 13:54:51 -07006253 std::shared_ptr<FakeApplicationHandle> application =
6254 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006255 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006256 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006257 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006258
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006259 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006260 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006261 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006262
6263 // Set focused application.
6264 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006265 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006266
6267 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006268 mDispatcher->onWindowInfosChanged(
6269 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006270 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006271 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006272 }
6273
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006274 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006275 InputDispatcherTest::TearDown();
6276
6277 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006278 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006279 }
6280
6281protected:
6282 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006283 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006284 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006285};
6286
6287// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6288// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6289// the onPointerDownOutsideFocus callback.
6290TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006292 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006293 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006295 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006296
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006297 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006298 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6299}
6300
6301// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6302// DOWN on the window that doesn't have focus. Ensure no window received the
6303// onPointerDownOutsideFocus callback.
6304TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006306 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6307 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006309 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006310
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006311 ASSERT_TRUE(mDispatcher->waitForIdle());
6312 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006313}
6314
6315// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6316// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6317TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006319 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006320 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006321 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006322
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006323 ASSERT_TRUE(mDispatcher->waitForIdle());
6324 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006325}
6326
6327// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6328// DOWN on the window that already has focus. Ensure no window received the
6329// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006330TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006332 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006333 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006335 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006336
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006337 ASSERT_TRUE(mDispatcher->waitForIdle());
6338 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006339}
6340
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006341// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6342// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6343TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6344 const MotionEvent event =
6345 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6346 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006347 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006348 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6349 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6352 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6353
6354 ASSERT_TRUE(mDispatcher->waitForIdle());
6355 mFakePolicy->assertOnPointerDownWasNotCalled();
6356 // Ensure that the unfocused window did not receive any FOCUS events.
6357 mUnfocusedWindow->assertNoEvents();
6358}
6359
chaviwaf87b3e2019-10-01 16:59:28 -07006360// These tests ensures we can send touch events to a single client when there are multiple input
6361// windows that point to the same client token.
6362class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6363 virtual void SetUp() override {
6364 InputDispatcherTest::SetUp();
6365
Chris Yea209fde2020-07-22 13:54:51 -07006366 std::shared_ptr<FakeApplicationHandle> application =
6367 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006368 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6369 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006370 mWindow1->setFrame(Rect(0, 0, 100, 100));
6371
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006372 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6373 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006374 mWindow2->setFrame(Rect(100, 100, 200, 200));
6375
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006376 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006377 }
6378
6379protected:
6380 sp<FakeWindowHandle> mWindow1;
6381 sp<FakeWindowHandle> mWindow2;
6382
6383 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006384 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006385 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6386 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006387 }
6388
6389 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6390 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006391 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006392 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006393
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006394 ASSERT_NE(nullptr, motionEvent)
6395 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006396
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006397 assertMotionAction(expectedAction, motionEvent->getAction());
6398 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006399
6400 for (size_t i = 0; i < points.size(); i++) {
6401 float expectedX = points[i].x;
6402 float expectedY = points[i].y;
6403
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006404 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006405 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006406 << ", got " << motionEvent->getX(i);
6407 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006408 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006409 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006410 }
6411 }
chaviw9eaa22c2020-07-01 16:21:27 -07006412
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006413 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006414 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006415 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6416 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006417
6418 // Always consume from window1 since it's the window that has the InputReceiver
6419 consumeMotionEvent(mWindow1, action, expectedPoints);
6420 }
chaviwaf87b3e2019-10-01 16:59:28 -07006421};
6422
6423TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6424 // Touch Window 1
6425 PointF touchedPoint = {10, 10};
6426 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006427 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006428
6429 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006430 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006431
6432 // Touch Window 2
6433 touchedPoint = {150, 150};
6434 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006435 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006436}
6437
chaviw9eaa22c2020-07-01 16:21:27 -07006438TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6439 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006440 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006441 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006442
6443 // Touch Window 1
6444 PointF touchedPoint = {10, 10};
6445 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006446 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006447 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006448 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006449
6450 // Touch Window 2
6451 touchedPoint = {150, 150};
6452 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006453 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6454 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006455
chaviw9eaa22c2020-07-01 16:21:27 -07006456 // Update the transform so rotation is set
6457 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006458 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006459 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6460 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006461}
6462
chaviw9eaa22c2020-07-01 16:21:27 -07006463TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006464 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006465 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006466
6467 // Touch Window 1
6468 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6469 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006470 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006471
6472 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006473 touchedPoints.push_back(PointF{150, 150});
6474 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006475 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006476
chaviw9eaa22c2020-07-01 16:21:27 -07006477 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006478 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006479 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006480
chaviw9eaa22c2020-07-01 16:21:27 -07006481 // Update the transform so rotation is set for Window 2
6482 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006483 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006484 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006485 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006486}
6487
chaviw9eaa22c2020-07-01 16:21:27 -07006488TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006489 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006490 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006491
6492 // Touch Window 1
6493 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6494 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006495 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006496
6497 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006498 touchedPoints.push_back(PointF{150, 150});
6499 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006500
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006501 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006502
6503 // Move both windows
6504 touchedPoints = {{20, 20}, {175, 175}};
6505 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6506 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6507
chaviw9eaa22c2020-07-01 16:21:27 -07006508 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006509
chaviw9eaa22c2020-07-01 16:21:27 -07006510 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006511 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006512 expectedPoints.pop_back();
6513
6514 // Touch Window 2
6515 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006516 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006517 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006518 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006519
6520 // Move both windows
6521 touchedPoints = {{20, 20}, {175, 175}};
6522 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6523 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6524
6525 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006526}
6527
6528TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6529 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006530 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006531
6532 // Touch Window 1
6533 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6534 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006535 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006536
6537 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006538 touchedPoints.push_back(PointF{150, 150});
6539 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006540
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006541 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006542
6543 // Move both windows
6544 touchedPoints = {{20, 20}, {175, 175}};
6545 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6546 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6547
chaviw9eaa22c2020-07-01 16:21:27 -07006548 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006549}
6550
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006551/**
6552 * When one of the windows is slippery, the touch should not slip into the other window with the
6553 * same input channel.
6554 */
6555TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6556 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006557 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006558
6559 // Touch down in window 1
6560 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6561 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6562 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6563
6564 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6565 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6566 // getting generated.
6567 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6568 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6569
6570 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6571}
6572
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006573/**
6574 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6575 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6576 * that the pointer is hovering over may have a different transform.
6577 */
6578TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006579 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006580
6581 // Start hover in window 1
6582 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6583 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6584 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6585 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6586
6587 // Move hover to window 2.
6588 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6589 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6590
6591 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6592 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6593 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6594}
6595
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006596class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6597 virtual void SetUp() override {
6598 InputDispatcherTest::SetUp();
6599
Chris Yea209fde2020-07-22 13:54:51 -07006600 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006601 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006602 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6603 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006604 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006605 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006606 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006607
6608 // Set focused application.
6609 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6610
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006611 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006612 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006613 mWindow->consumeFocusEvent(true);
6614 }
6615
6616 virtual void TearDown() override {
6617 InputDispatcherTest::TearDown();
6618 mWindow.clear();
6619 }
6620
6621protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006622 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07006623 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006624 sp<FakeWindowHandle> mWindow;
6625 static constexpr PointF WINDOW_LOCATION = {20, 20};
6626
6627 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006629 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006630 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006632 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006633 WINDOW_LOCATION));
6634 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006635
6636 sp<FakeWindowHandle> addSpyWindow() {
6637 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006638 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006639 spy->setTrustedOverlay(true);
6640 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006641 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006642 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006643 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006644 return spy;
6645 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006646};
6647
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006648// Send a tap and respond, which should not cause an ANR.
6649TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6650 tapOnWindow();
6651 mWindow->consumeMotionDown();
6652 mWindow->consumeMotionUp();
6653 ASSERT_TRUE(mDispatcher->waitForIdle());
6654 mFakePolicy->assertNotifyAnrWasNotCalled();
6655}
6656
6657// Send a regular key and respond, which should not cause an ANR.
6658TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006660 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6661 ASSERT_TRUE(mDispatcher->waitForIdle());
6662 mFakePolicy->assertNotifyAnrWasNotCalled();
6663}
6664
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006665TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6666 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006667 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006668 mWindow->consumeFocusEvent(false);
6669
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006670 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006671 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6672 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00006673 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006675 // Key will not go to window because we have no focused window.
6676 // The 'no focused window' ANR timer should start instead.
6677
6678 // Now, the focused application goes away.
6679 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6680 // The key should get dropped and there should be no ANR.
6681
6682 ASSERT_TRUE(mDispatcher->waitForIdle());
6683 mFakePolicy->assertNotifyAnrWasNotCalled();
6684}
6685
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006686// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006687// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6688// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006689TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006692 WINDOW_LOCATION));
6693
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006694 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6695 ASSERT_TRUE(sequenceNum);
6696 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006697 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006698
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006699 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006700 mWindow->consumeMotionEvent(
6701 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006702 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006703 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006704}
6705
6706// Send a key to the app and have the app not respond right away.
6707TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6708 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006710 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6711 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006712 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006713 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006714 ASSERT_TRUE(mDispatcher->waitForIdle());
6715}
6716
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006717// We have a focused application, but no focused window
6718TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006719 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006720 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006721 mWindow->consumeFocusEvent(false);
6722
6723 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006726 WINDOW_LOCATION));
6727 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6728 mDispatcher->waitForIdle();
6729 mFakePolicy->assertNotifyAnrWasNotCalled();
6730
6731 // Once a focused event arrives, we get an ANR for this application
6732 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6733 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006734 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006735 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006736 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006737 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006738 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006739 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006740 ASSERT_TRUE(mDispatcher->waitForIdle());
6741}
6742
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006743/**
6744 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6745 * there will not be an ANR.
6746 */
6747TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6748 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006749 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006750 mWindow->consumeFocusEvent(false);
6751
6752 KeyEvent event;
6753 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6754 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6755
6756 // Define a valid key down event that is stale (too old).
6757 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006758 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006759 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006760
6761 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6762
6763 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006764 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006765 InputEventInjectionSync::WAIT_FOR_RESULT,
6766 INJECT_EVENT_TIMEOUT, policyFlags);
6767 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6768 << "Injection should fail because the event is stale";
6769
6770 ASSERT_TRUE(mDispatcher->waitForIdle());
6771 mFakePolicy->assertNotifyAnrWasNotCalled();
6772 mWindow->assertNoEvents();
6773}
6774
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006775// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006776// Make sure that we don't notify policy twice about the same ANR.
6777TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006778 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006779 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006780 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006781
6782 // Once a focused event arrives, we get an ANR for this application
6783 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6784 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006785 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006786 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6787 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006788 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006789 const std::chrono::duration appTimeout =
6790 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6791 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006792
Vishnu Naire4df8752022-09-08 09:17:55 -07006793 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006794 // ANR should not be raised again. It is up to policy to do that if it desires.
6795 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006796
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006797 // If we now get a focused window, the ANR should stop, but the policy handles that via
6798 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799 ASSERT_TRUE(mDispatcher->waitForIdle());
6800}
6801
6802// We have a focused application, but no focused window
6803TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006804 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006805 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806 mWindow->consumeFocusEvent(false);
6807
6808 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006809 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006810
Vishnu Naire4df8752022-09-08 09:17:55 -07006811 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6812 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813
6814 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006815 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006816 ASSERT_TRUE(mDispatcher->waitForIdle());
6817 mWindow->assertNoEvents();
6818}
6819
6820/**
6821 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6822 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6823 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6824 * the ANR mechanism should still work.
6825 *
6826 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6827 * DOWN event, while not responding on the second one.
6828 */
6829TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6830 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006831 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006832 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6833 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6834 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006835 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006836
6837 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006838 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006839 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6840 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6841 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006842 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006843
6844 // We have now sent down and up. Let's consume first event and then ANR on the second.
6845 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6846 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006847 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006848}
6849
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006850// A spy window can receive an ANR
6851TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6852 sp<FakeWindowHandle> spy = addSpyWindow();
6853
6854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006855 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006856 WINDOW_LOCATION));
6857 mWindow->consumeMotionDown();
6858
6859 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6860 ASSERT_TRUE(sequenceNum);
6861 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006862 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006863
6864 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006865 spy->consumeMotionEvent(
6866 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006867 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006868 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006869}
6870
6871// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006872// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006873TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6874 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006875
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006877 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006878 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006880
6881 // Stuck on the ACTION_UP
6882 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006883 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006885 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006886 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006887 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6888 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006889
6890 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6891 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006892 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006893 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006894 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006895}
6896
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006897// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006898// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006899TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6900 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006901
6902 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006903 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6904 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006905
6906 mWindow->consumeMotionDown();
6907 // Stuck on the ACTION_UP
6908 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006909 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006910
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006911 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006912 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006913 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6914 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006915
6916 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6917 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006918 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006919 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006920 spy->assertNoEvents();
6921}
6922
6923TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006924 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006925
6926 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6927
6928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006929 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006930 WINDOW_LOCATION));
6931
6932 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6933 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6934 ASSERT_TRUE(consumeSeq);
6935
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006936 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
6937 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006938
6939 monitor.finishEvent(*consumeSeq);
6940 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6941
6942 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006943 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006944}
6945
6946// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6947// process events, you don't get an anr. When the window later becomes unresponsive again, you
6948// get an ANR again.
6949// 1. tap -> block on ACTION_UP -> receive ANR
6950// 2. consume all pending events (= queue becomes healthy again)
6951// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6952TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6953 tapOnWindow();
6954
6955 mWindow->consumeMotionDown();
6956 // Block on ACTION_UP
6957 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006958 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006959 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6960 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006961 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006962 mWindow->assertNoEvents();
6963
6964 tapOnWindow();
6965 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006966 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006967 mWindow->consumeMotionUp();
6968
6969 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006970 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006971 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006972 mWindow->assertNoEvents();
6973}
6974
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006975// If a connection remains unresponsive for a while, make sure policy is only notified once about
6976// it.
6977TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006979 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006980 WINDOW_LOCATION));
6981
6982 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006983 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006984 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006985 // 'notifyConnectionUnresponsive' should only be called once per connection
6986 mFakePolicy->assertNotifyAnrWasNotCalled();
6987 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006988 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006989 mWindow->consumeMotionEvent(
6990 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006991 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006992 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006993 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006994 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006995}
6996
6997/**
6998 * 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 -07006999 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007000 *
7001 * Warning!!!
7002 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7003 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007004 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007005 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7006 *
7007 * If that value changes, this test should also change.
7008 */
7009TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7010 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007011 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007012
7013 tapOnWindow();
7014 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7015 ASSERT_TRUE(downSequenceNum);
7016 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7017 ASSERT_TRUE(upSequenceNum);
7018 // Don't finish the events yet, and send a key
7019 // Injection will "succeed" because we will eventually give up and send the key to the focused
7020 // window even if motions are still being processed. But because the injection timeout is short,
7021 // we will receive INJECTION_TIMED_OUT as the result.
7022
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007023 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007024 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7025 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007026 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007027 // Key will not be sent to the window, yet, because the window is still processing events
7028 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007029 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7030 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7031 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7032 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007033
7034 std::this_thread::sleep_for(500ms);
7035 // if we wait long enough though, dispatcher will give up, and still send the key
7036 // to the focused window, even though we have not yet finished the motion event
7037 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7038 mWindow->finishEvent(*downSequenceNum);
7039 mWindow->finishEvent(*upSequenceNum);
7040}
7041
7042/**
7043 * If a window is processing a motion event, and then a key event comes in, the key event should
7044 * not go to the focused window until the motion is processed.
7045 * If then a new motion comes in, then the pending key event should be going to the currently
7046 * focused window right away.
7047 */
7048TEST_F(InputDispatcherSingleWindowAnr,
7049 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7050 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007051 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007052
7053 tapOnWindow();
7054 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7055 ASSERT_TRUE(downSequenceNum);
7056 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7057 ASSERT_TRUE(upSequenceNum);
7058 // Don't finish the events yet, and send a key
7059 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007061 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7062 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007063 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007064 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7065 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7066 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7067 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007068
7069 // Now tap down again. It should cause the pending key to go to the focused window right away.
7070 tapOnWindow();
7071 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7072 // the other events yet. We can finish events in any order.
7073 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7074 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7075 mWindow->consumeMotionDown();
7076 mWindow->consumeMotionUp();
7077 mWindow->assertNoEvents();
7078}
7079
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007080/**
7081 * Send an event to the app and have the app not respond right away.
7082 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7083 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7084 * At some point, the window becomes responsive again.
7085 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7086 */
7087TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7089 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7090 .build());
7091
7092 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7093 ASSERT_TRUE(sequenceNum);
7094 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7095 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7096
7097 mWindow->finishEvent(*sequenceNum);
7098 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7099 ASSERT_TRUE(mDispatcher->waitForIdle());
7100 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7101
7102 // Now that the window is responsive, let's continue the gesture.
7103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7104 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7105 .build());
7106
7107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7108 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7109 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7110 .build());
7111
7112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7113 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7114 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7115 .build());
7116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7117 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7118 .build());
7119 // We already canceled this pointer, so the window shouldn't get any new events.
7120 mWindow->assertNoEvents();
7121
7122 // Start another one.
7123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7124 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7125 .build());
7126 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7127}
7128
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007129class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7130 virtual void SetUp() override {
7131 InputDispatcherTest::SetUp();
7132
Chris Yea209fde2020-07-22 13:54:51 -07007133 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007134 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007135 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7136 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007137 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007138 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007139 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007140
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007141 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7142 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007143 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007144 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145
7146 // Set focused application.
7147 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007148 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007149
7150 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007151 mDispatcher->onWindowInfosChanged(
7152 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007153 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007154 mFocusedWindow->consumeFocusEvent(true);
7155 }
7156
7157 virtual void TearDown() override {
7158 InputDispatcherTest::TearDown();
7159
7160 mUnfocusedWindow.clear();
7161 mFocusedWindow.clear();
7162 }
7163
7164protected:
Chris Yea209fde2020-07-22 13:54:51 -07007165 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007166 sp<FakeWindowHandle> mUnfocusedWindow;
7167 sp<FakeWindowHandle> mFocusedWindow;
7168 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7169 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7170 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7171
7172 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7173
7174 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7175
7176private:
7177 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007179 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007180 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007182 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007183 location));
7184 }
7185};
7186
7187// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7188// should be ANR'd first.
7189TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007191 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007192 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007194 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007195 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007196 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007197 // We consumed all events, so no ANR
7198 ASSERT_TRUE(mDispatcher->waitForIdle());
7199 mFakePolicy->assertNotifyAnrWasNotCalled();
7200
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007202 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007203 FOCUSED_WINDOW_LOCATION));
7204 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7205 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007206
7207 const std::chrono::duration timeout =
7208 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007209 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007210 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7211 // sequence to make it consistent
7212 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007213 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007214 mFocusedWindow->consumeMotionDown();
7215 // This cancel is generated because the connection was unresponsive
7216 mFocusedWindow->consumeMotionCancel();
7217 mFocusedWindow->assertNoEvents();
7218 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007219 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007220 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7221 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007222 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007223}
7224
7225// If we have 2 windows with identical timeouts that are both unresponsive,
7226// it doesn't matter which order they should have ANR.
7227// But we should receive ANR for both.
7228TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7229 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007230 mUnfocusedWindow->setDispatchingTimeout(
7231 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007232 mDispatcher->onWindowInfosChanged(
7233 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007234
7235 tapOnFocusedWindow();
7236 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007237 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007238 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7239 mFocusedWindow->getDispatchingTimeout(
7240 DISPATCHING_TIMEOUT)),
7241 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7242
7243 ASSERT_THAT(anrConnectionTokens,
7244 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7245 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007246
7247 ASSERT_TRUE(mDispatcher->waitForIdle());
7248 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007249
7250 mFocusedWindow->consumeMotionDown();
7251 mFocusedWindow->consumeMotionUp();
7252 mUnfocusedWindow->consumeMotionOutside();
7253
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007254 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7255 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007256
7257 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007258 ASSERT_THAT(responsiveTokens,
7259 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7260 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007261 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007262}
7263
7264// If a window is already not responding, the second tap on the same window should be ignored.
7265// We should also log an error to account for the dropped event (not tested here).
7266// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7267TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7268 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007269 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007270 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007271 // Receive the events, but don't respond
7272 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7273 ASSERT_TRUE(downEventSequenceNum);
7274 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7275 ASSERT_TRUE(upEventSequenceNum);
7276 const std::chrono::duration timeout =
7277 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007278 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279
7280 // Tap once again
7281 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007282 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007283 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007284 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007285 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007286 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007287 FOCUSED_WINDOW_LOCATION));
7288 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7289 // valid touch target
7290 mUnfocusedWindow->assertNoEvents();
7291
7292 // Consume the first tap
7293 mFocusedWindow->finishEvent(*downEventSequenceNum);
7294 mFocusedWindow->finishEvent(*upEventSequenceNum);
7295 ASSERT_TRUE(mDispatcher->waitForIdle());
7296 // The second tap did not go to the focused window
7297 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007298 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007299 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7300 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007301 mFakePolicy->assertNotifyAnrWasNotCalled();
7302}
7303
7304// If you tap outside of all windows, there will not be ANR
7305TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007306 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007307 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007308 LOCATION_OUTSIDE_ALL_WINDOWS));
7309 ASSERT_TRUE(mDispatcher->waitForIdle());
7310 mFakePolicy->assertNotifyAnrWasNotCalled();
7311}
7312
7313// Since the focused window is paused, tapping on it should not produce any events
7314TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7315 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007316 mDispatcher->onWindowInfosChanged(
7317 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007319 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007320 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007321 FOCUSED_WINDOW_LOCATION));
7322
7323 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7324 ASSERT_TRUE(mDispatcher->waitForIdle());
7325 // Should not ANR because the window is paused, and touches shouldn't go to it
7326 mFakePolicy->assertNotifyAnrWasNotCalled();
7327
7328 mFocusedWindow->assertNoEvents();
7329 mUnfocusedWindow->assertNoEvents();
7330}
7331
7332/**
7333 * 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 -07007334 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007335 * If a different window becomes focused at this time, the key should go to that window instead.
7336 *
7337 * Warning!!!
7338 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7339 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007340 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007341 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7342 *
7343 * If that value changes, this test should also change.
7344 */
7345TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7346 // Set a long ANR timeout to prevent it from triggering
7347 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007348 mDispatcher->onWindowInfosChanged(
7349 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007350
7351 tapOnUnfocusedWindow();
7352 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7353 ASSERT_TRUE(downSequenceNum);
7354 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7355 ASSERT_TRUE(upSequenceNum);
7356 // Don't finish the events yet, and send a key
7357 // Injection will succeed because we will eventually give up and send the key to the focused
7358 // window even if motions are still being processed.
7359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007360 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007361 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7362 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007364 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007365 // and the key remains pending, waiting for the touch events to be processed.
7366 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7367 // under the hood.
7368 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7369 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007370
7371 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007372 mFocusedWindow->setFocusable(false);
7373 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007374 mDispatcher->onWindowInfosChanged(
7375 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007376 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377
7378 // Focus events should precede the key events
7379 mUnfocusedWindow->consumeFocusEvent(true);
7380 mFocusedWindow->consumeFocusEvent(false);
7381
7382 // Finish the tap events, which should unblock dispatcher
7383 mUnfocusedWindow->finishEvent(*downSequenceNum);
7384 mUnfocusedWindow->finishEvent(*upSequenceNum);
7385
7386 // Now that all queues are cleared and no backlog in the connections, the key event
7387 // can finally go to the newly focused "mUnfocusedWindow".
7388 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7389 mFocusedWindow->assertNoEvents();
7390 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007391 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007392}
7393
7394// When the touch stream is split across 2 windows, and one of them does not respond,
7395// then ANR should be raised and the touch should be canceled for the unresponsive window.
7396// The other window should not be affected by that.
7397TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7398 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007399 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7400 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7401 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007402 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007403 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007404
7405 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007406 mDispatcher->notifyMotion(
7407 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7408 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007409
7410 const std::chrono::duration timeout =
7411 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007412 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007413
7414 mUnfocusedWindow->consumeMotionDown();
7415 mFocusedWindow->consumeMotionDown();
7416 // Focused window may or may not receive ACTION_MOVE
7417 // But it should definitely receive ACTION_CANCEL due to the ANR
7418 InputEvent* event;
7419 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7420 ASSERT_TRUE(moveOrCancelSequenceNum);
7421 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7422 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007423 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007424 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7425 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7426 mFocusedWindow->consumeMotionCancel();
7427 } else {
7428 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7429 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007430 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007431 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7432 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007433
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434 mUnfocusedWindow->assertNoEvents();
7435 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007436 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007437}
7438
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007439/**
7440 * If we have no focused window, and a key comes in, we start the ANR timer.
7441 * The focused application should add a focused window before the timer runs out to prevent ANR.
7442 *
7443 * If the user touches another application during this time, the key should be dropped.
7444 * Next, if a new focused window comes in, without toggling the focused application,
7445 * then no ANR should occur.
7446 *
7447 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7448 * but in some cases the policy may not update the focused application.
7449 */
7450TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7451 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7452 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007453 focusedApplication->setDispatchingTimeout(200ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007454 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7455 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7456 mFocusedWindow->setFocusable(false);
7457
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007458 mDispatcher->onWindowInfosChanged(
7459 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007460 mFocusedWindow->consumeFocusEvent(false);
7461
7462 // Send a key. The ANR timer should start because there is no focused window.
7463 // 'focusedApplication' will get blamed if this timer completes.
7464 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007465 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007466 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7467 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00007468 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007470
7471 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7472 // then the injected touches won't cause the focused event to get dropped.
7473 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7474 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7475 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7476 // For this test, it means that the key would get delivered to the window once it becomes
7477 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007478 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007479
7480 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007481 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7482 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7483 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007484
7485 // We do not consume the motion right away, because that would require dispatcher to first
7486 // process (== drop) the key event, and by that time, ANR will be raised.
7487 // Set the focused window first.
7488 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007489 mDispatcher->onWindowInfosChanged(
7490 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007491 setFocusedWindow(mFocusedWindow);
7492 mFocusedWindow->consumeFocusEvent(true);
7493 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7494 // to another application. This could be a bug / behaviour in the policy.
7495
7496 mUnfocusedWindow->consumeMotionDown();
7497
7498 ASSERT_TRUE(mDispatcher->waitForIdle());
7499 // Should not ANR because we actually have a focused window. It was just added too slowly.
7500 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7501}
7502
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007503// These tests ensure we cannot send touch events to a window that's positioned behind a window
7504// that has feature NO_INPUT_CHANNEL.
7505// Layout:
7506// Top (closest to user)
7507// mNoInputWindow (above all windows)
7508// mBottomWindow
7509// Bottom (furthest from user)
7510class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7511 virtual void SetUp() override {
7512 InputDispatcherTest::SetUp();
7513
7514 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007515 mNoInputWindow =
7516 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7517 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007518 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007519 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007520 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7521 // It's perfectly valid for this window to not have an associated input channel
7522
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007523 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7524 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007525 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7526
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007527 mDispatcher->onWindowInfosChanged(
7528 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007529 }
7530
7531protected:
7532 std::shared_ptr<FakeApplicationHandle> mApplication;
7533 sp<FakeWindowHandle> mNoInputWindow;
7534 sp<FakeWindowHandle> mBottomWindow;
7535};
7536
7537TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7538 PointF touchedPoint = {10, 10};
7539
Prabir Pradhan678438e2023-04-13 19:32:51 +00007540 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7541 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7542 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007543
7544 mNoInputWindow->assertNoEvents();
7545 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7546 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7547 // and therefore should prevent mBottomWindow from receiving touches
7548 mBottomWindow->assertNoEvents();
7549}
7550
7551/**
7552 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7553 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7554 */
7555TEST_F(InputDispatcherMultiWindowOcclusionTests,
7556 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007557 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7558 "Window with input channel and NO_INPUT_CHANNEL",
7559 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007560
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007561 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007562 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007563 mDispatcher->onWindowInfosChanged(
7564 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007565
7566 PointF touchedPoint = {10, 10};
7567
Prabir Pradhan678438e2023-04-13 19:32:51 +00007568 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7569 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7570 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007571
7572 mNoInputWindow->assertNoEvents();
7573 mBottomWindow->assertNoEvents();
7574}
7575
Vishnu Nair958da932020-08-21 17:12:37 -07007576class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7577protected:
7578 std::shared_ptr<FakeApplicationHandle> mApp;
7579 sp<FakeWindowHandle> mWindow;
7580 sp<FakeWindowHandle> mMirror;
7581
7582 virtual void SetUp() override {
7583 InputDispatcherTest::SetUp();
7584 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007585 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7586 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7587 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007588 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7589 mWindow->setFocusable(true);
7590 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007591 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007592 }
7593};
7594
7595TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7596 // Request focus on a mirrored window
7597 setFocusedWindow(mMirror);
7598
7599 // window gets focused
7600 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007602 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007603 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7604}
7605
7606// A focused & mirrored window remains focused only if the window and its mirror are both
7607// focusable.
7608TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7609 setFocusedWindow(mMirror);
7610
7611 // window gets focused
7612 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007614 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007615 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007617 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007618 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7619
7620 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007621 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007622
7623 // window loses focus since one of the windows associated with the token in not focusable
7624 mWindow->consumeFocusEvent(false);
7625
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007626 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007627 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007628 mWindow->assertNoEvents();
7629}
7630
7631// A focused & mirrored window remains focused until the window and its mirror both become
7632// invisible.
7633TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7634 setFocusedWindow(mMirror);
7635
7636 // window gets focused
7637 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007640 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007643 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7644
7645 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007646 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007647
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007649 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007650 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007652 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007653 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7654
7655 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007656 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007657
7658 // window loses focus only after all windows associated with the token become invisible.
7659 mWindow->consumeFocusEvent(false);
7660
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007661 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007662 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007663 mWindow->assertNoEvents();
7664}
7665
7666// A focused & mirrored window remains focused until both windows are removed.
7667TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7668 setFocusedWindow(mMirror);
7669
7670 // window gets focused
7671 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007674 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007676 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007677 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7678
7679 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007680 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007681
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007683 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007684 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007687 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7688
7689 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007690 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007691 mWindow->consumeFocusEvent(false);
7692
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007693 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007695 mWindow->assertNoEvents();
7696}
7697
7698// Focus request can be pending until one window becomes visible.
7699TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7700 // Request focus on an invisible mirror.
7701 mWindow->setVisible(false);
7702 mMirror->setVisible(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 setFocusedWindow(mMirror);
7705
7706 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007708 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7709 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007710
7711 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007712 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007713
7714 // window gets focused
7715 mWindow->consumeFocusEvent(true);
7716 // window gets the pending key event
7717 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7718}
Prabir Pradhan99987712020-11-10 18:43:05 -08007719
7720class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7721protected:
7722 std::shared_ptr<FakeApplicationHandle> mApp;
7723 sp<FakeWindowHandle> mWindow;
7724 sp<FakeWindowHandle> mSecondWindow;
7725
7726 void SetUp() override {
7727 InputDispatcherTest::SetUp();
7728 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007729 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007730 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007731 mSecondWindow =
7732 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007733 mSecondWindow->setFocusable(true);
7734
7735 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007736 mDispatcher->onWindowInfosChanged(
7737 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08007738
7739 setFocusedWindow(mWindow);
7740 mWindow->consumeFocusEvent(true);
7741 }
7742
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007743 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007744 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007745 }
7746
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007747 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7748 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007749 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007750 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7751 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007752 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007753 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007754 }
7755};
7756
7757TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7758 // Ensure that capture cannot be obtained for unfocused windows.
7759 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7760 mFakePolicy->assertSetPointerCaptureNotCalled();
7761 mSecondWindow->assertNoEvents();
7762
7763 // Ensure that capture can be enabled from the focus window.
7764 requestAndVerifyPointerCapture(mWindow, true);
7765
7766 // Ensure that capture cannot be disabled from a window that does not have capture.
7767 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7768 mFakePolicy->assertSetPointerCaptureNotCalled();
7769
7770 // Ensure that capture can be disabled from the window with capture.
7771 requestAndVerifyPointerCapture(mWindow, false);
7772}
7773
7774TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007775 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007776
7777 setFocusedWindow(mSecondWindow);
7778
7779 // Ensure that the capture disabled event was sent first.
7780 mWindow->consumeCaptureEvent(false);
7781 mWindow->consumeFocusEvent(false);
7782 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007783 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007784
7785 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007786 notifyPointerCaptureChanged({});
7787 notifyPointerCaptureChanged(request);
7788 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007789 mWindow->assertNoEvents();
7790 mSecondWindow->assertNoEvents();
7791 mFakePolicy->assertSetPointerCaptureNotCalled();
7792}
7793
7794TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007795 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007796
7797 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007798 notifyPointerCaptureChanged({});
7799 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007800
7801 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007802 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007803 mWindow->consumeCaptureEvent(false);
7804 mWindow->assertNoEvents();
7805}
7806
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007807TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7808 requestAndVerifyPointerCapture(mWindow, true);
7809
7810 // The first window loses focus.
7811 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007812 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007813 mWindow->consumeCaptureEvent(false);
7814
7815 // Request Pointer Capture from the second window before the notification from InputReader
7816 // arrives.
7817 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007818 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007819
7820 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007821 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007822
7823 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007824 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007825
7826 mSecondWindow->consumeFocusEvent(true);
7827 mSecondWindow->consumeCaptureEvent(true);
7828}
7829
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007830TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7831 // App repeatedly enables and disables capture.
7832 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7833 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7834 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7835 mFakePolicy->assertSetPointerCaptureCalled(false);
7836 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7837 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7838
7839 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7840 // first request is now stale, this should do nothing.
7841 notifyPointerCaptureChanged(firstRequest);
7842 mWindow->assertNoEvents();
7843
7844 // InputReader notifies that the second request was enabled.
7845 notifyPointerCaptureChanged(secondRequest);
7846 mWindow->consumeCaptureEvent(true);
7847}
7848
Prabir Pradhan7092e262022-05-03 16:51:09 +00007849TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7850 requestAndVerifyPointerCapture(mWindow, true);
7851
7852 // App toggles pointer capture off and on.
7853 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7854 mFakePolicy->assertSetPointerCaptureCalled(false);
7855
7856 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7857 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7858
7859 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7860 // preceding "disable" request.
7861 notifyPointerCaptureChanged(enableRequest);
7862
7863 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7864 // any notifications.
7865 mWindow->assertNoEvents();
7866}
7867
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007868class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7869protected:
7870 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007871
7872 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7873 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7874
7875 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7876 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7877
7878 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7879 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7880 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7881 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7882 MAXIMUM_OBSCURING_OPACITY);
7883
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007884 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7885 static constexpr gui::Uid APP_B_UID{10002};
7886 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007887
7888 sp<FakeWindowHandle> mTouchWindow;
7889
7890 virtual void SetUp() override {
7891 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007892 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007893 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7894 }
7895
7896 virtual void TearDown() override {
7897 InputDispatcherTest::TearDown();
7898 mTouchWindow.clear();
7899 }
7900
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007901 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007902 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007903 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007904 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007905 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007906 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007907 return window;
7908 }
7909
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007910 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007911 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7912 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007913 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007914 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007915 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007916 return window;
7917 }
7918
7919 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007920 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7921 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7922 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007923 }
7924};
7925
7926TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007927 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007928 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007929 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007930
7931 touch();
7932
7933 mTouchWindow->assertNoEvents();
7934}
7935
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007936TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007937 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7938 const sp<FakeWindowHandle>& w =
7939 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007940 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00007941
7942 touch();
7943
7944 mTouchWindow->assertNoEvents();
7945}
7946
7947TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007948 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7949 const sp<FakeWindowHandle>& w =
7950 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007951 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007952
7953 touch();
7954
7955 w->assertNoEvents();
7956}
7957
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007958TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007959 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007960 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007961
7962 touch();
7963
7964 mTouchWindow->consumeAnyMotionDown();
7965}
7966
7967TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007968 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007969 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007970 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007971 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007972
7973 touch({PointF{100, 100}});
7974
7975 mTouchWindow->consumeAnyMotionDown();
7976}
7977
7978TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007979 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007980 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007981 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007982
7983 touch();
7984
7985 mTouchWindow->consumeAnyMotionDown();
7986}
7987
7988TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7989 const sp<FakeWindowHandle>& w =
7990 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007991 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007992
7993 touch();
7994
7995 mTouchWindow->consumeAnyMotionDown();
7996}
7997
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007998TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7999 const sp<FakeWindowHandle>& w =
8000 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008001 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008002
8003 touch();
8004
8005 w->assertNoEvents();
8006}
8007
8008/**
8009 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8010 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8011 * window, the occluding window will still receive ACTION_OUTSIDE event.
8012 */
8013TEST_F(InputDispatcherUntrustedTouchesTest,
8014 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8015 const sp<FakeWindowHandle>& w =
8016 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008017 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008018 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008019
8020 touch();
8021
8022 w->consumeMotionOutside();
8023}
8024
8025TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8026 const sp<FakeWindowHandle>& w =
8027 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008028 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008029 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008030
8031 touch();
8032
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008033 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008034}
8035
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008036TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008037 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008038 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8039 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008040 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008041
8042 touch();
8043
8044 mTouchWindow->consumeAnyMotionDown();
8045}
8046
8047TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8048 const sp<FakeWindowHandle>& w =
8049 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8050 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008051 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008052
8053 touch();
8054
8055 mTouchWindow->consumeAnyMotionDown();
8056}
8057
8058TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008059 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008060 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8061 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008062 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008063
8064 touch();
8065
8066 mTouchWindow->assertNoEvents();
8067}
8068
8069TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8070 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8071 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008072 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8073 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008074 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008075 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8076 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008077 mDispatcher->onWindowInfosChanged(
8078 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008079
8080 touch();
8081
8082 mTouchWindow->assertNoEvents();
8083}
8084
8085TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8086 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8087 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008088 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8089 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008090 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008091 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8092 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008093 mDispatcher->onWindowInfosChanged(
8094 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008095
8096 touch();
8097
8098 mTouchWindow->consumeAnyMotionDown();
8099}
8100
8101TEST_F(InputDispatcherUntrustedTouchesTest,
8102 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8103 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008104 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8105 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008106 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008107 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8108 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008109 mDispatcher->onWindowInfosChanged(
8110 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008111
8112 touch();
8113
8114 mTouchWindow->consumeAnyMotionDown();
8115}
8116
8117TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8118 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008119 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8120 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008121 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008122 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8123 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008124 mDispatcher->onWindowInfosChanged(
8125 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008126
8127 touch();
8128
8129 mTouchWindow->assertNoEvents();
8130}
8131
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008132TEST_F(InputDispatcherUntrustedTouchesTest,
8133 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8134 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008135 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8136 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008137 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008138 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8139 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008140 mDispatcher->onWindowInfosChanged(
8141 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008142
8143 touch();
8144
8145 mTouchWindow->assertNoEvents();
8146}
8147
8148TEST_F(InputDispatcherUntrustedTouchesTest,
8149 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8150 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008151 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8152 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008153 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008154 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8155 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008156 mDispatcher->onWindowInfosChanged(
8157 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008158
8159 touch();
8160
8161 mTouchWindow->consumeAnyMotionDown();
8162}
8163
8164TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8165 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008166 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8167 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008168 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008169
8170 touch();
8171
8172 mTouchWindow->consumeAnyMotionDown();
8173}
8174
8175TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8176 const sp<FakeWindowHandle>& w =
8177 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008178 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008179
8180 touch();
8181
8182 mTouchWindow->consumeAnyMotionDown();
8183}
8184
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008185TEST_F(InputDispatcherUntrustedTouchesTest,
8186 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8187 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8188 const sp<FakeWindowHandle>& w =
8189 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008190 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008191
8192 touch();
8193
8194 mTouchWindow->assertNoEvents();
8195}
8196
8197TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8198 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8199 const sp<FakeWindowHandle>& w =
8200 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008201 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008202
8203 touch();
8204
8205 mTouchWindow->consumeAnyMotionDown();
8206}
8207
8208TEST_F(InputDispatcherUntrustedTouchesTest,
8209 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8210 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8211 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008212 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8213 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008214 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008215
8216 touch();
8217
8218 mTouchWindow->consumeAnyMotionDown();
8219}
8220
8221TEST_F(InputDispatcherUntrustedTouchesTest,
8222 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8223 const sp<FakeWindowHandle>& w1 =
8224 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8225 OPACITY_BELOW_THRESHOLD);
8226 const sp<FakeWindowHandle>& w2 =
8227 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8228 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008229 mDispatcher->onWindowInfosChanged(
8230 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008231
8232 touch();
8233
8234 mTouchWindow->assertNoEvents();
8235}
8236
8237/**
8238 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8239 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8240 * (which alone would result in allowing touches) does not affect the blocking behavior.
8241 */
8242TEST_F(InputDispatcherUntrustedTouchesTest,
8243 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8244 const sp<FakeWindowHandle>& wB =
8245 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8246 OPACITY_BELOW_THRESHOLD);
8247 const sp<FakeWindowHandle>& wC =
8248 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8249 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008250 mDispatcher->onWindowInfosChanged(
8251 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008252
8253 touch();
8254
8255 mTouchWindow->assertNoEvents();
8256}
8257
8258/**
8259 * This test is testing that a window from a different UID but with same application token doesn't
8260 * block the touch. Apps can share the application token for close UI collaboration for example.
8261 */
8262TEST_F(InputDispatcherUntrustedTouchesTest,
8263 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8264 const sp<FakeWindowHandle>& w =
8265 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8266 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008267 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008268
8269 touch();
8270
8271 mTouchWindow->consumeAnyMotionDown();
8272}
8273
arthurhungb89ccb02020-12-30 16:19:01 +08008274class InputDispatcherDragTests : public InputDispatcherTest {
8275protected:
8276 std::shared_ptr<FakeApplicationHandle> mApp;
8277 sp<FakeWindowHandle> mWindow;
8278 sp<FakeWindowHandle> mSecondWindow;
8279 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008280 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008281 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8282 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008283
8284 void SetUp() override {
8285 InputDispatcherTest::SetUp();
8286 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008287 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008288 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008289
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008290 mSecondWindow =
8291 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008292 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008293
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008294 mSpyWindow =
8295 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008296 mSpyWindow->setSpy(true);
8297 mSpyWindow->setTrustedOverlay(true);
8298 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8299
arthurhungb89ccb02020-12-30 16:19:01 +08008300 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008301 mDispatcher->onWindowInfosChanged(
8302 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8303 {},
8304 0,
8305 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008306 }
8307
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008308 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8309 switch (fromSource) {
8310 case AINPUT_SOURCE_TOUCHSCREEN:
8311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008312 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008313 ADISPLAY_ID_DEFAULT, {50, 50}))
8314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8315 break;
8316 case AINPUT_SOURCE_STYLUS:
8317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008318 injectMotionEvent(*mDispatcher,
8319 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8320 AINPUT_SOURCE_STYLUS)
8321 .buttonState(
8322 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8323 .pointer(PointerBuilder(0, ToolType::STYLUS)
8324 .x(50)
8325 .y(50))
8326 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008327 break;
8328 case AINPUT_SOURCE_MOUSE:
8329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008330 injectMotionEvent(*mDispatcher,
8331 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8332 AINPUT_SOURCE_MOUSE)
8333 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8334 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8335 ToolType::MOUSE)
8336 .x(50)
8337 .y(50))
8338 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008339 break;
8340 default:
8341 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8342 }
arthurhungb89ccb02020-12-30 16:19:01 +08008343
8344 // Window should receive motion event.
8345 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008346 // Spy window should also receive motion event
8347 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008348 }
8349
8350 // Start performing drag, we will create a drag window and transfer touch to it.
8351 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8352 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008353 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008354 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008355 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008356 }
arthurhungb89ccb02020-12-30 16:19:01 +08008357
8358 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008359 mDragWindow =
8360 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008361 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008362 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8363 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8364 {},
8365 0,
8366 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008367
8368 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008369 bool transferred =
8370 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008371 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008372 if (transferred) {
8373 mWindow->consumeMotionCancel();
8374 mDragWindow->consumeMotionDown();
8375 }
8376 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008377 }
8378};
8379
8380TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008381 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008382
8383 // Move on window.
8384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008385 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008386 ADISPLAY_ID_DEFAULT, {50, 50}))
8387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8388 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8389 mWindow->consumeDragEvent(false, 50, 50);
8390 mSecondWindow->assertNoEvents();
8391
8392 // Move to another window.
8393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008394 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008395 ADISPLAY_ID_DEFAULT, {150, 50}))
8396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8397 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8398 mWindow->consumeDragEvent(true, 150, 50);
8399 mSecondWindow->consumeDragEvent(false, 50, 50);
8400
8401 // Move back to original window.
8402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008403 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008404 ADISPLAY_ID_DEFAULT, {50, 50}))
8405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8406 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8407 mWindow->consumeDragEvent(false, 50, 50);
8408 mSecondWindow->consumeDragEvent(true, -50, 50);
8409
8410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008411 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8412 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08008413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8414 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8415 mWindow->assertNoEvents();
8416 mSecondWindow->assertNoEvents();
8417}
8418
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008419TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008420 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008421
8422 // No cancel event after drag start
8423 mSpyWindow->assertNoEvents();
8424
8425 const MotionEvent secondFingerDownEvent =
8426 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8427 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008428 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8429 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008430 .build();
8431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008432 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008433 InputEventInjectionSync::WAIT_FOR_RESULT))
8434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8435
8436 // Receives cancel for first pointer after next pointer down
8437 mSpyWindow->consumeMotionCancel();
8438 mSpyWindow->consumeMotionDown();
8439
8440 mSpyWindow->assertNoEvents();
8441}
8442
arthurhungf452d0b2021-01-06 00:19:52 +08008443TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008444 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008445
8446 // Move on window.
8447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008448 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08008449 ADISPLAY_ID_DEFAULT, {50, 50}))
8450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8451 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8452 mWindow->consumeDragEvent(false, 50, 50);
8453 mSecondWindow->assertNoEvents();
8454
8455 // Move to another window.
8456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008457 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08008458 ADISPLAY_ID_DEFAULT, {150, 50}))
8459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8460 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8461 mWindow->consumeDragEvent(true, 150, 50);
8462 mSecondWindow->consumeDragEvent(false, 50, 50);
8463
8464 // drop to another window.
8465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008466 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08008467 {150, 50}))
8468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8469 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008470 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008471 mWindow->assertNoEvents();
8472 mSecondWindow->assertNoEvents();
8473}
8474
arthurhung6d4bed92021-03-17 11:59:33 +08008475TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008476 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008477
8478 // Move on window and keep button pressed.
8479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008480 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008481 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8482 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008484 .build()))
8485 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8486 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8487 mWindow->consumeDragEvent(false, 50, 50);
8488 mSecondWindow->assertNoEvents();
8489
8490 // Move to another window and release button, expect to drop item.
8491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008492 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008493 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8494 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008495 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008496 .build()))
8497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8498 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8499 mWindow->assertNoEvents();
8500 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008501 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008502
8503 // nothing to the window.
8504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008505 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008506 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8507 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008508 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008509 .build()))
8510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8511 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8512 mWindow->assertNoEvents();
8513 mSecondWindow->assertNoEvents();
8514}
8515
Arthur Hung54745652022-04-20 07:17:41 +00008516TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008517 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008518
8519 // Set second window invisible.
8520 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008521 mDispatcher->onWindowInfosChanged(
8522 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08008523
8524 // Move on window.
8525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008526 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008527 ADISPLAY_ID_DEFAULT, {50, 50}))
8528 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8529 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8530 mWindow->consumeDragEvent(false, 50, 50);
8531 mSecondWindow->assertNoEvents();
8532
8533 // Move to another window.
8534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008535 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008536 ADISPLAY_ID_DEFAULT, {150, 50}))
8537 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8538 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8539 mWindow->consumeDragEvent(true, 150, 50);
8540 mSecondWindow->assertNoEvents();
8541
8542 // drop to another window.
8543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008544 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008545 {150, 50}))
8546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8547 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008548 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008549 mWindow->assertNoEvents();
8550 mSecondWindow->assertNoEvents();
8551}
8552
Arthur Hung54745652022-04-20 07:17:41 +00008553TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008554 // Ensure window could track pointerIds if it didn't support split touch.
8555 mWindow->setPreventSplitting(true);
8556
Arthur Hung54745652022-04-20 07:17:41 +00008557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008558 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00008559 {50, 50}))
8560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8561 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8562
8563 const MotionEvent secondFingerDownEvent =
8564 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8565 .displayId(ADISPLAY_ID_DEFAULT)
8566 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008567 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8568 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008569 .build();
8570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008571 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008572 InputEventInjectionSync::WAIT_FOR_RESULT))
8573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008574 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008575
8576 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008577 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008578}
8579
8580TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8581 // First down on second window.
8582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008583 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00008584 {150, 50}))
8585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8586
8587 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8588
8589 // Second down on first window.
8590 const MotionEvent secondFingerDownEvent =
8591 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8592 .displayId(ADISPLAY_ID_DEFAULT)
8593 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008594 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8595 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008596 .build();
8597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008598 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008599 InputEventInjectionSync::WAIT_FOR_RESULT))
8600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8601 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8602
8603 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008604 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008605
8606 // Move on window.
8607 const MotionEvent secondFingerMoveEvent =
8608 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8609 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008610 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8611 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008612 .build();
8613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008614 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008615 InputEventInjectionSync::WAIT_FOR_RESULT));
8616 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8617 mWindow->consumeDragEvent(false, 50, 50);
8618 mSecondWindow->consumeMotionMove();
8619
8620 // Release the drag pointer should perform drop.
8621 const MotionEvent secondFingerUpEvent =
8622 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8623 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008624 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8625 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008626 .build();
8627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008628 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008629 InputEventInjectionSync::WAIT_FOR_RESULT));
8630 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008631 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008632 mWindow->assertNoEvents();
8633 mSecondWindow->consumeMotionMove();
8634}
8635
Arthur Hung3915c1f2022-05-31 07:17:17 +00008636TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008637 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008638
8639 // Update window of second display.
8640 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008641 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008642 mDispatcher->onWindowInfosChanged(
8643 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8644 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8645 {},
8646 0,
8647 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008648
8649 // Let second display has a touch state.
8650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008651 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008652 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8653 AINPUT_SOURCE_TOUCHSCREEN)
8654 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008655 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008656 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008657 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008658 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008659 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008660 mDispatcher->onWindowInfosChanged(
8661 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8662 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8663 {},
8664 0,
8665 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008666
8667 // Move on window.
8668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008669 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008670 ADISPLAY_ID_DEFAULT, {50, 50}))
8671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8672 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8673 mWindow->consumeDragEvent(false, 50, 50);
8674 mSecondWindow->assertNoEvents();
8675
8676 // Move to another window.
8677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008678 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008679 ADISPLAY_ID_DEFAULT, {150, 50}))
8680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8681 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8682 mWindow->consumeDragEvent(true, 150, 50);
8683 mSecondWindow->consumeDragEvent(false, 50, 50);
8684
8685 // drop to another window.
8686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008687 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008688 {150, 50}))
8689 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8690 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008691 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008692 mWindow->assertNoEvents();
8693 mSecondWindow->assertNoEvents();
8694}
8695
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008696TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8697 startDrag(true, AINPUT_SOURCE_MOUSE);
8698 // Move on window.
8699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008700 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008701 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8702 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008703 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008704 .x(50)
8705 .y(50))
8706 .build()))
8707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8708 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8709 mWindow->consumeDragEvent(false, 50, 50);
8710 mSecondWindow->assertNoEvents();
8711
8712 // Move to another window.
8713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008714 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008715 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8716 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008717 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008718 .x(150)
8719 .y(50))
8720 .build()))
8721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8722 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8723 mWindow->consumeDragEvent(true, 150, 50);
8724 mSecondWindow->consumeDragEvent(false, 50, 50);
8725
8726 // drop to another window.
8727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008728 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008729 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8730 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008731 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008732 .x(150)
8733 .y(50))
8734 .build()))
8735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8736 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008737 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008738 mWindow->assertNoEvents();
8739 mSecondWindow->assertNoEvents();
8740}
8741
Vishnu Nair062a8672021-09-03 16:07:44 -07008742class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8743
8744TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008746 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8747 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008748 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008749 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8750 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008751 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008752 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008753 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008754
8755 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008756 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008757 window->assertNoEvents();
8758
Prabir Pradhan678438e2023-04-13 19:32:51 +00008759 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8760 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8762 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008763 window->assertNoEvents();
8764
8765 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008766 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008767 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008768
Prabir Pradhan678438e2023-04-13 19:32:51 +00008769 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008770 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8771
Prabir Pradhan678438e2023-04-13 19:32:51 +00008772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8773 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008774 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8775 window->assertNoEvents();
8776}
8777
8778TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8779 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8780 std::make_shared<FakeApplicationHandle>();
8781 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008782 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8783 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008784 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008785 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008786 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8789 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008790 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008791 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008792 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8793 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008794 mDispatcher->onWindowInfosChanged(
8795 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008796 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008797 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008798
8799 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008800 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008801 window->assertNoEvents();
8802
Prabir Pradhan678438e2023-04-13 19:32:51 +00008803 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8804 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008805 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8806 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008807 window->assertNoEvents();
8808
8809 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008810 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008811 mDispatcher->onWindowInfosChanged(
8812 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008813
Prabir Pradhan678438e2023-04-13 19:32:51 +00008814 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008815 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8816
Prabir Pradhan678438e2023-04-13 19:32:51 +00008817 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8818 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008819 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8820 window->assertNoEvents();
8821}
8822
8823TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8824 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8825 std::make_shared<FakeApplicationHandle>();
8826 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008827 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8828 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008829 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008830 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008831 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008832 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008833 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8834 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008835 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008836 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008837 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8838 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008839 mDispatcher->onWindowInfosChanged(
8840 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008841 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008842 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008843
8844 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008845 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008846 window->assertNoEvents();
8847
Prabir Pradhan678438e2023-04-13 19:32:51 +00008848 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8849 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008850 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8851 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008852 window->assertNoEvents();
8853
8854 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008855 mDispatcher->onWindowInfosChanged(
8856 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008857
Prabir Pradhan678438e2023-04-13 19:32:51 +00008858 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008859 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8860
Prabir Pradhan678438e2023-04-13 19:32:51 +00008861 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8862 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008863 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8864 window->assertNoEvents();
8865}
8866
Antonio Kantekf16f2832021-09-28 04:39:20 +00008867class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8868protected:
8869 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008870 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008871 sp<FakeWindowHandle> mWindow;
8872 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008873 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008874
8875 void SetUp() override {
8876 InputDispatcherTest::SetUp();
8877
8878 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008879 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008880 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008881 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008882 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008883 mSecondWindow =
8884 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008885 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008886 mThirdWindow =
8887 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8888 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8889 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008890
8891 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008892 mDispatcher->onWindowInfosChanged(
8893 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
8894 {},
8895 0,
8896 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00008897 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008898 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008899
Antonio Kantek15beb512022-06-13 22:35:41 +00008900 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008901 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008902 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008903 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8904 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008905 mThirdWindow->assertNoEvents();
8906 }
8907
8908 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8909 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008910 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008911 SECOND_DISPLAY_ID)) {
8912 mWindow->assertNoEvents();
8913 mSecondWindow->assertNoEvents();
8914 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008915 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008916 }
8917
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008918 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008919 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008920 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8921 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008922 mWindow->consumeTouchModeEvent(inTouchMode);
8923 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008924 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008925 }
8926};
8927
Antonio Kantek26defcf2022-02-08 01:12:27 +00008928TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008929 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008930 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8931 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008932 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008933}
8934
Antonio Kantek26defcf2022-02-08 01:12:27 +00008935TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8936 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008937 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008938 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008939 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008940 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008941 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008942 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008943 mWindow->assertNoEvents();
8944 mSecondWindow->assertNoEvents();
8945}
8946
8947TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8948 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008949 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008950 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008951 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008952 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008953 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008954}
8955
Antonio Kantekf16f2832021-09-28 04:39:20 +00008956TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008957 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008958 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8959 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008960 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008961 mWindow->assertNoEvents();
8962 mSecondWindow->assertNoEvents();
8963}
8964
Antonio Kantek15beb512022-06-13 22:35:41 +00008965TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8966 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8967 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8968 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008969 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008970 mWindow->assertNoEvents();
8971 mSecondWindow->assertNoEvents();
8972 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8973}
8974
Antonio Kantek48710e42022-03-24 14:19:30 -07008975TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8976 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8978 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07008979 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8980 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8981
8982 // Then remove focus.
8983 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008984 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07008985
8986 // Assert that caller can switch touch mode by owning one of the last interacted window.
8987 const WindowInfo& windowInfo = *mWindow->getInfo();
8988 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8989 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008990 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008991}
8992
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008993class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8994public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008995 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008996 std::shared_ptr<FakeApplicationHandle> application =
8997 std::make_shared<FakeApplicationHandle>();
8998 std::string name = "Fake Spy ";
8999 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009000 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9001 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009002 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009003 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009004 return spy;
9005 }
9006
9007 sp<FakeWindowHandle> createForeground() {
9008 std::shared_ptr<FakeApplicationHandle> application =
9009 std::make_shared<FakeApplicationHandle>();
9010 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009011 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9012 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009013 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009014 return window;
9015 }
9016
9017private:
9018 int mSpyCount{0};
9019};
9020
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009021using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009022/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009023 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9024 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009025TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009026 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009027 ScopedSilentDeath _silentDeath;
9028
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009029 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009030 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009031 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009032 ".* not a trusted overlay");
9033}
9034
9035/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009036 * Input injection into a display with a spy window but no foreground windows should succeed.
9037 */
9038TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009039 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009040 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009041
9042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009043 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9045 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9046}
9047
9048/**
9049 * Verify the order in which different input windows receive events. The touched foreground window
9050 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9051 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9052 * receive events before ones belows it.
9053 *
9054 * Here, we set up a scenario with four windows in the following Z order from the top:
9055 * spy1, spy2, window, spy3.
9056 * We then inject an event and verify that the foreground "window" receives it first, followed by
9057 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9058 * window.
9059 */
9060TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9061 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009062 auto spy1 = createSpy();
9063 auto spy2 = createSpy();
9064 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009065 mDispatcher->onWindowInfosChanged(
9066 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009067 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9068 const size_t numChannels = channels.size();
9069
Michael Wright8e9a8562022-02-09 13:44:29 +00009070 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009071 if (!epollFd.ok()) {
9072 FAIL() << "Failed to create epoll fd";
9073 }
9074
9075 for (size_t i = 0; i < numChannels; i++) {
9076 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9077 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9078 FAIL() << "Failed to add fd to epoll";
9079 }
9080 }
9081
9082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009083 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9085
9086 std::vector<size_t> eventOrder;
9087 std::vector<struct epoll_event> events(numChannels);
9088 for (;;) {
9089 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9090 (100ms).count());
9091 if (nFds < 0) {
9092 FAIL() << "Failed to call epoll_wait";
9093 }
9094 if (nFds == 0) {
9095 break; // epoll_wait timed out
9096 }
9097 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009098 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009099 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009100 channels[i]->consumeMotionDown();
9101 }
9102 }
9103
9104 // Verify the order in which the events were received.
9105 EXPECT_EQ(3u, eventOrder.size());
9106 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9107 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9108 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9109}
9110
9111/**
9112 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9113 */
9114TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9115 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009116 auto spy = createSpy();
9117 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009118 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009119
9120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009121 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009122 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9123 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9124 spy->assertNoEvents();
9125}
9126
9127/**
9128 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9129 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9130 * to the window.
9131 */
9132TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9133 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009134 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009135 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009136 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009137
9138 // Inject an event outside the spy window's touchable region.
9139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009140 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009141 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9142 window->consumeMotionDown();
9143 spy->assertNoEvents();
9144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009145 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9147 window->consumeMotionUp();
9148 spy->assertNoEvents();
9149
9150 // Inject an event inside the spy window's touchable region.
9151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009152 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009153 {5, 10}))
9154 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9155 window->consumeMotionDown();
9156 spy->consumeMotionDown();
9157}
9158
9159/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009160 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009161 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009162 */
9163TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9164 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009165 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009166 auto spy = createSpy();
9167 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009168 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009169 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009170 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009171
9172 // Inject an event outside the spy window's frame and touchable region.
9173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009174 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009175 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9177 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009178 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009179}
9180
9181/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009182 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9183 * pointers that are down within its bounds.
9184 */
9185TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9186 auto windowLeft = createForeground();
9187 windowLeft->setFrame({0, 0, 100, 200});
9188 auto windowRight = createForeground();
9189 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009190 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009191 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009192 mDispatcher->onWindowInfosChanged(
9193 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009194
9195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009196 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009197 {50, 50}))
9198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9199 windowLeft->consumeMotionDown();
9200 spy->consumeMotionDown();
9201
9202 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009203 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009204 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009205 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9206 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009207 .build();
9208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009209 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009210 InputEventInjectionSync::WAIT_FOR_RESULT))
9211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9212 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009213 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009214}
9215
9216/**
9217 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9218 * the spy should receive the second pointer with ACTION_DOWN.
9219 */
9220TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9221 auto window = createForeground();
9222 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009223 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009224 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009225 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009226
9227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009228 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009229 {50, 50}))
9230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9231 window->consumeMotionDown();
9232 spyRight->assertNoEvents();
9233
9234 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009235 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009236 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009237 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9238 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009239 .build();
9240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009241 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009242 InputEventInjectionSync::WAIT_FOR_RESULT))
9243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009244 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009245 spyRight->consumeMotionDown();
9246}
9247
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009248/**
9249 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9250 * windows should be allowed to control split touch.
9251 */
9252TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009253 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009254 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009255 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009256 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009257
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009258 auto window = createForeground();
9259 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009260
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009261 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009262
9263 // First finger down, no window touched.
9264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009265 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009266 {100, 200}))
9267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9268 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9269 window->assertNoEvents();
9270
9271 // Second finger down on window, the window should receive touch down.
9272 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009273 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009274 .displayId(ADISPLAY_ID_DEFAULT)
9275 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009276 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9277 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009278 .build();
9279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009280 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009281 InputEventInjectionSync::WAIT_FOR_RESULT))
9282 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9283
9284 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009285 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009286}
9287
9288/**
9289 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9290 * do not receive key events.
9291 */
9292TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009293 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009294 spy->setFocusable(false);
9295
9296 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009297 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009298 setFocusedWindow(window);
9299 window->consumeFocusEvent(true);
9300
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009302 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9303 window->consumeKeyDown(ADISPLAY_ID_NONE);
9304
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009306 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9307 window->consumeKeyUp(ADISPLAY_ID_NONE);
9308
9309 spy->assertNoEvents();
9310}
9311
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009312using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9313
9314/**
9315 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9316 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9317 */
9318TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9319 auto window = createForeground();
9320 auto spy1 = createSpy();
9321 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009322 mDispatcher->onWindowInfosChanged(
9323 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009324
9325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009326 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009327 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9328 window->consumeMotionDown();
9329 spy1->consumeMotionDown();
9330 spy2->consumeMotionDown();
9331
9332 // Pilfer pointers from the second spy window.
9333 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9334 spy2->assertNoEvents();
9335 spy1->consumeMotionCancel();
9336 window->consumeMotionCancel();
9337
9338 // The rest of the gesture should only be sent to the second spy window.
9339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009340 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009341 ADISPLAY_ID_DEFAULT))
9342 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9343 spy2->consumeMotionMove();
9344 spy1->assertNoEvents();
9345 window->assertNoEvents();
9346}
9347
9348/**
9349 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9350 * in the middle of the gesture.
9351 */
9352TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9353 auto window = createForeground();
9354 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009355 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009356
9357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009358 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9360 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9361 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9362
9363 window->releaseChannel();
9364
9365 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9366
9367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009368 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9370 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9371}
9372
9373/**
9374 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9375 * the spy, but not to any other windows.
9376 */
9377TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9378 auto spy = createSpy();
9379 auto window = createForeground();
9380
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009381 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009382
9383 // First finger down on the window and the spy.
9384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009385 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009386 {100, 200}))
9387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9388 spy->consumeMotionDown();
9389 window->consumeMotionDown();
9390
9391 // Spy window pilfers the pointers.
9392 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9393 window->consumeMotionCancel();
9394
9395 // Second finger down on the window and spy, but the window should not receive the pointer down.
9396 const MotionEvent secondFingerDownEvent =
9397 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9398 .displayId(ADISPLAY_ID_DEFAULT)
9399 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009400 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9401 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009402 .build();
9403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009404 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009405 InputEventInjectionSync::WAIT_FOR_RESULT))
9406 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9407
Harry Cutts33476232023-01-30 19:57:29 +00009408 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009409
9410 // Third finger goes down outside all windows, so injection should fail.
9411 const MotionEvent thirdFingerDownEvent =
9412 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9413 .displayId(ADISPLAY_ID_DEFAULT)
9414 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009415 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9416 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9417 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009418 .build();
9419 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009420 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009421 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009422 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009423
9424 spy->assertNoEvents();
9425 window->assertNoEvents();
9426}
9427
9428/**
9429 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9430 */
9431TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9432 auto spy = createSpy();
9433 spy->setFrame(Rect(0, 0, 100, 100));
9434 auto window = createForeground();
9435 window->setFrame(Rect(0, 0, 200, 200));
9436
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 // First finger down on the window only
9440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009441 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009442 {150, 150}))
9443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9444 window->consumeMotionDown();
9445
9446 // Second finger down on the spy and window
9447 const MotionEvent secondFingerDownEvent =
9448 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9449 .displayId(ADISPLAY_ID_DEFAULT)
9450 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009451 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9452 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009453 .build();
9454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009455 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009456 InputEventInjectionSync::WAIT_FOR_RESULT))
9457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9458 spy->consumeMotionDown();
9459 window->consumeMotionPointerDown(1);
9460
9461 // Third finger down on the spy and window
9462 const MotionEvent thirdFingerDownEvent =
9463 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9464 .displayId(ADISPLAY_ID_DEFAULT)
9465 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009466 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9467 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9468 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009469 .build();
9470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009471 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009472 InputEventInjectionSync::WAIT_FOR_RESULT))
9473 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9474 spy->consumeMotionPointerDown(1);
9475 window->consumeMotionPointerDown(2);
9476
9477 // Spy window pilfers the pointers.
9478 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009479 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9480 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009481
9482 spy->assertNoEvents();
9483 window->assertNoEvents();
9484}
9485
9486/**
9487 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9488 * other windows should be canceled. If this results in the cancellation of all pointers for some
9489 * window, then that window should receive ACTION_CANCEL.
9490 */
9491TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9492 auto spy = createSpy();
9493 spy->setFrame(Rect(0, 0, 100, 100));
9494 auto window = createForeground();
9495 window->setFrame(Rect(0, 0, 200, 200));
9496
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009497 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009498
9499 // First finger down on both spy and window
9500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009501 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009502 {10, 10}))
9503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9504 window->consumeMotionDown();
9505 spy->consumeMotionDown();
9506
9507 // Second finger down on the spy and window
9508 const MotionEvent secondFingerDownEvent =
9509 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9510 .displayId(ADISPLAY_ID_DEFAULT)
9511 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009512 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9513 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009514 .build();
9515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009516 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009517 InputEventInjectionSync::WAIT_FOR_RESULT))
9518 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9519 spy->consumeMotionPointerDown(1);
9520 window->consumeMotionPointerDown(1);
9521
9522 // Spy window pilfers the pointers.
9523 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9524 window->consumeMotionCancel();
9525
9526 spy->assertNoEvents();
9527 window->assertNoEvents();
9528}
9529
9530/**
9531 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9532 * be sent to other windows
9533 */
9534TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9535 auto spy = createSpy();
9536 spy->setFrame(Rect(0, 0, 100, 100));
9537 auto window = createForeground();
9538 window->setFrame(Rect(0, 0, 200, 200));
9539
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009540 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009541
9542 // First finger down on both window and spy
9543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009545 {10, 10}))
9546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9547 window->consumeMotionDown();
9548 spy->consumeMotionDown();
9549
9550 // Spy window pilfers the pointers.
9551 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9552 window->consumeMotionCancel();
9553
9554 // Second finger down on the window only
9555 const MotionEvent secondFingerDownEvent =
9556 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9557 .displayId(ADISPLAY_ID_DEFAULT)
9558 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009559 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9560 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009561 .build();
9562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009563 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009564 InputEventInjectionSync::WAIT_FOR_RESULT))
9565 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9566 window->consumeMotionDown();
9567 window->assertNoEvents();
9568
9569 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9570 spy->consumeMotionMove();
9571 spy->assertNoEvents();
9572}
9573
Prabir Pradhand65552b2021-10-07 11:23:50 -07009574class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9575public:
9576 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9577 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9578 std::make_shared<FakeApplicationHandle>();
9579 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009580 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9581 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009582 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009583 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009584 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009585 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009586 overlay->setTrustedOverlay(true);
9587
9588 std::shared_ptr<FakeApplicationHandle> application =
9589 std::make_shared<FakeApplicationHandle>();
9590 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009591 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9592 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009593 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009594 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009595
9596 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009597 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009598 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009599 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009600 return {std::move(overlay), std::move(window)};
9601 }
9602
9603 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009604 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009605 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009606 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009607 }
9608
9609 void sendStylusEvent(int32_t action) {
9610 NotifyMotionArgs motionArgs =
9611 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9612 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009613 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009614 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009615 }
9616};
9617
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009618using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9619
9620TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009621 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009622 ScopedSilentDeath _silentDeath;
9623
Prabir Pradhand65552b2021-10-07 11:23:50 -07009624 auto [overlay, window] = setupStylusOverlayScenario();
9625 overlay->setTrustedOverlay(false);
9626 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009627 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
9628 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -07009629 ".* not a trusted overlay");
9630}
9631
9632TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9633 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009634 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009635
9636 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9637 overlay->consumeMotionDown();
9638 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9639 overlay->consumeMotionUp();
9640
9641 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9642 window->consumeMotionDown();
9643 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9644 window->consumeMotionUp();
9645
9646 overlay->assertNoEvents();
9647 window->assertNoEvents();
9648}
9649
9650TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9651 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009652 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009653 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009654
9655 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9656 overlay->consumeMotionDown();
9657 window->consumeMotionDown();
9658 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9659 overlay->consumeMotionUp();
9660 window->consumeMotionUp();
9661
9662 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9663 window->consumeMotionDown();
9664 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9665 window->consumeMotionUp();
9666
9667 overlay->assertNoEvents();
9668 window->assertNoEvents();
9669}
9670
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009671/**
9672 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9673 * The scenario is as follows:
9674 * - The stylus interceptor overlay is configured as a spy window.
9675 * - The stylus interceptor spy receives the start of a new stylus gesture.
9676 * - It pilfers pointers and then configures itself to no longer be a spy.
9677 * - The stylus interceptor continues to receive the rest of the gesture.
9678 */
9679TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9680 auto [overlay, window] = setupStylusOverlayScenario();
9681 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009682 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009683
9684 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9685 overlay->consumeMotionDown();
9686 window->consumeMotionDown();
9687
9688 // The interceptor pilfers the pointers.
9689 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9690 window->consumeMotionCancel();
9691
9692 // The interceptor configures itself so that it is no longer a spy.
9693 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009694 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009695
9696 // It continues to receive the rest of the stylus gesture.
9697 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9698 overlay->consumeMotionMove();
9699 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9700 overlay->consumeMotionUp();
9701
9702 window->assertNoEvents();
9703}
9704
Prabir Pradhan5735a322022-04-11 17:23:34 +00009705struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009706 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009707 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009708 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9709 std::unique_ptr<InputDispatcher>& mDispatcher;
9710
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009711 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009712 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9713
9714 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009715 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009716 ADISPLAY_ID_DEFAULT, {100, 200},
9717 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9718 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9719 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9720 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9721 }
9722
9723 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009724 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009725 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009726 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009727 mPolicyFlags);
9728 }
9729
9730 sp<FakeWindowHandle> createWindow() const {
9731 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9732 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009733 sp<FakeWindowHandle> window =
9734 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9735 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009736 window->setOwnerInfo(mPid, mUid);
9737 return window;
9738 }
9739};
9740
9741using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9742
9743TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009744 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009745 auto window = owner.createWindow();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009747
9748 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9749 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9750 window->consumeMotionDown();
9751
9752 setFocusedWindow(window);
9753 window->consumeFocusEvent(true);
9754
9755 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9756 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9757 window->consumeKeyDown(ADISPLAY_ID_NONE);
9758}
9759
9760TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009761 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009762 auto window = owner.createWindow();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009763 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009764
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009765 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009766 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9767 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9768
9769 setFocusedWindow(window);
9770 window->consumeFocusEvent(true);
9771
9772 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9773 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9774 window->assertNoEvents();
9775}
9776
9777TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009778 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009779 auto window = owner.createWindow();
9780 auto spy = owner.createWindow();
9781 spy->setSpy(true);
9782 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009783 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009784
9785 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9786 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9787 spy->consumeMotionDown();
9788 window->consumeMotionDown();
9789}
9790
9791TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009792 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009793 auto window = owner.createWindow();
9794
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009795 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009796 auto randosSpy = rando.createWindow();
9797 randosSpy->setSpy(true);
9798 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009799 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009800
9801 // The event is targeted at owner's window, so injection should succeed, but the spy should
9802 // not receive the event.
9803 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9804 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9805 randosSpy->assertNoEvents();
9806 window->consumeMotionDown();
9807}
9808
9809TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009810 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009811 auto window = owner.createWindow();
9812
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009813 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009814 auto randosSpy = rando.createWindow();
9815 randosSpy->setSpy(true);
9816 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009817 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009818
9819 // A user that has injection permission can inject into any window.
9820 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009821 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009822 ADISPLAY_ID_DEFAULT));
9823 randosSpy->consumeMotionDown();
9824 window->consumeMotionDown();
9825
9826 setFocusedWindow(randosSpy);
9827 randosSpy->consumeFocusEvent(true);
9828
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009829 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +00009830 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9831 window->assertNoEvents();
9832}
9833
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009834TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009835 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009836 auto window = owner.createWindow();
9837
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009838 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009839 auto randosWindow = rando.createWindow();
9840 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9841 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009842 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009843
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009844 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009845 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9846 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9847 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009848 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009849}
9850
Garfield Tane84e6f92019-08-29 17:28:41 -07009851} // namespace android::inputdispatcher