blob: 73ab0dae41a8aece368759221810c1300e3b65fd [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"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhan81e89fe2024-03-20 21:17:09 +000019#include "FakeInputDispatcherPolicy.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhanc5340732024-03-20 22:53:52 +000021#include "FakeWindows.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000022#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080023
Cody Heiner166a5af2023-07-07 12:25:00 -070024#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000025#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070026#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080027#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070029#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070030#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000032#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000033#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080034#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080036#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100037#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070038#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070039#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080041#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080044#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070045#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080046#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080047#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Garfield Tan1c7bc862020-01-28 13:24:04 -080049using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050050using android::gui::FocusRequest;
51using android::gui::TouchOcclusionMode;
52using android::gui::WindowInfo;
53using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080054using android::os::InputEventInjectionResult;
55using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080056
Garfield Tane84e6f92019-08-29 17:28:41 -070057namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080060using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000061using testing::Not;
Siarhei Vishniakou85eb5802024-04-01 11:40:59 -070062using testing::Pointee;
63using testing::UnorderedElementsAre;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070064
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070065namespace {
66
Michael Wrightd02c5b62014-02-10 15:10:22 -080067// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000068static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080069
70// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000071static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080072static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080073
Jeff Brownf086ddb2014-02-11 14:28:48 -080074// An arbitrary display id.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070075constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Linnan Li13bf76a2024-05-05 19:18:02 +080076constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
Jeff Brownf086ddb2014-02-11 14:28:48 -080077
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000078// Ensure common actions are interchangeable between keys and motions for convenience.
79static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
80static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
82static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
83static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
84static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070085static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080086static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070087static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080088static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080089static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080090/**
91 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
92 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
93 * index 0) is the new pointer going down. The same pointer could have been placed at a different
94 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
95 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
96 * pointer id=0 leaves but the pointer id=1 remains.
97 */
98static constexpr int32_t POINTER_0_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100static constexpr int32_t POINTER_1_DOWN =
101 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +0000102static constexpr int32_t POINTER_2_DOWN =
103 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000104static constexpr int32_t POINTER_3_DOWN =
105 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000106static constexpr int32_t POINTER_0_UP =
107 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800108static constexpr int32_t POINTER_1_UP =
109 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000110static constexpr int32_t POINTER_2_UP =
111 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800112
Antonio Kantek15beb512022-06-13 22:35:41 +0000113// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000115static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000116
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000118static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000119
Linnan Li72352222024-04-12 18:55:57 +0800120static constexpr int EXPECTED_WALLPAPER_FLAGS =
Arthur Hungc539dbb2022-12-08 07:45:36 +0000121 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800123using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124
Gang Wang342c9272020-01-13 13:15:04 -0500125/**
126 * Return a DOWN key event with KEYCODE_A.
127 */
128static KeyEvent getTestKeyEvent() {
129 KeyEvent event;
130
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700131 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
132 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
133 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500134 return event;
135}
136
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700137/**
138 * Provide a local override for a flag value. The value is restored when the object of this class
139 * goes out of scope.
140 * This class is not intended to be used directly, because its usage is cumbersome.
141 * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
142 */
143class ScopedFlagOverride {
144public:
145 ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
146 : mInitialValue(read()), mWriteValue(write) {
147 mWriteValue(value);
148 }
149 ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
150
151private:
152 const bool mInitialValue;
153 std::function<void(bool)> mWriteValue;
154};
155
156typedef bool (*readFlagValueFunction)();
157typedef void (*writeFlagValueFunction)(bool);
158
159/**
160 * Use this macro to locally override a flag value.
161 * Example usage:
162 * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
163 * Note: this works by creating a local variable in your current scope. Don't call this twice for
164 * the same flag, because the variable names will clash!
165 */
166#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
167 readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
168 writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
169 ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
170
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172
Michael Wrightd02c5b62014-02-10 15:10:22 -0800173// --- InputDispatcherTest ---
174
175class InputDispatcherTest : public testing::Test {
176protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000177 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700178 std::unique_ptr<InputDispatcher> mDispatcher;
Prabir Pradhanc5340732024-03-20 22:53:52 +0000179 std::shared_ptr<VerifyingTrace> mVerifyingTrace;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 void SetUp() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000182 mVerifyingTrace = std::make_shared<VerifyingTrace>();
183 FakeWindowHandle::sOnEventReceivedCallback = [this](const auto& _1, const auto& _2) {
184 handleEventReceivedByWindow(_1, _2);
185 };
186
Prabir Pradhana41d2442023-04-20 21:30:40 +0000187 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000188 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
189 std::make_unique<FakeInputTracingBackend>(
Prabir Pradhanc5340732024-03-20 22:53:52 +0000190 mVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700191
Harry Cutts101ee9b2023-07-06 18:04:14 +0000192 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000193 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700194 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195 }
196
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000197 void TearDown() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000198 ASSERT_NO_FATAL_FAILURE(mVerifyingTrace->verifyExpectedEventsTraced());
199 FakeWindowHandle::sOnEventReceivedCallback = nullptr;
200
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700201 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000202 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700203 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205
Prabir Pradhanc5340732024-03-20 22:53:52 +0000206 void handleEventReceivedByWindow(const std::unique_ptr<InputEvent>& event,
207 const gui::WindowInfo& info) {
208 if (!event) {
209 return;
210 }
211
212 switch (event->getType()) {
213 case InputEventType::KEY: {
214 mVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), info.id);
215 break;
216 }
217 case InputEventType::MOTION: {
218 mVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
219 info.id);
220 break;
221 }
222 default:
223 break;
224 }
225 }
226
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700227 /**
228 * Used for debugging when writing the test
229 */
230 void dumpDispatcherState() {
231 std::string dump;
232 mDispatcher->dump(dump);
233 std::stringstream ss(dump);
234 std::string to;
235
236 while (std::getline(ss, to, '\n')) {
237 ALOGE("%s", to.c_str());
238 }
239 }
Vishnu Nair958da932020-08-21 17:12:37 -0700240
Chavi Weingarten847e8512023-03-29 00:26:09 +0000241 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700242 FocusRequest request;
243 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000244 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700245 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Linnan Li13bf76a2024-05-05 19:18:02 +0800246 request.displayId = window->getInfo()->displayId.val();
Vishnu Nair958da932020-08-21 17:12:37 -0700247 mDispatcher->setFocusedWindow(request);
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249};
250
Michael Wrightd02c5b62014-02-10 15:10:22 -0800251TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
252 KeyEvent event;
253
254 // Rejects undefined key actions.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700255 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
256 ui::LogicalDisplayId::INVALID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000257 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600258 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800259 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000260 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000261 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 << "Should reject key events with undefined action.";
263
264 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700265 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
266 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0,
267 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800268 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000269 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000270 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 << "Should reject key events with ACTION_MULTIPLE.";
272}
273
274TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
275 MotionEvent event;
276 PointerProperties pointerProperties[MAX_POINTERS + 1];
277 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800278 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279 pointerProperties[i].clear();
280 pointerProperties[i].id = i;
281 pointerCoords[i].clear();
282 }
283
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800284 // Some constants commonly used below
285 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
286 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
287 constexpr int32_t metaState = AMETA_NONE;
288 constexpr MotionClassification classification = MotionClassification::NONE;
289
chaviw9eaa22c2020-07-01 16:21:27 -0700290 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800292 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000293 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700294 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700295 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
296 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000297 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000299 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000300 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 << "Should reject motion events with undefined action.";
302
303 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800304 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800305 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
306 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
307 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
308 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000309 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800310 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000311 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000312 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 << "Should reject motion events with pointer down index too large.";
314
Garfield Tanfbe732e2020-01-24 11:26:14 -0800315 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700316 AMOTION_EVENT_ACTION_POINTER_DOWN |
317 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700318 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
319 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700320 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000321 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800322 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000323 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000324 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800325 << "Should reject motion events with pointer down index too small.";
326
327 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800328 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800329 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
330 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
331 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
332 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000333 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800334 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000335 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000336 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 << "Should reject motion events with pointer up index too large.";
338
Garfield Tanfbe732e2020-01-24 11:26:14 -0800339 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700340 AMOTION_EVENT_ACTION_POINTER_UP |
341 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700342 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
343 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700344 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000345 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000347 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000348 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 << "Should reject motion events with pointer up index too small.";
350
351 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800352 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
353 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700354 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700355 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
356 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000357 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800358 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000359 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000360 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361 << "Should reject motion events with 0 pointers.";
362
Garfield Tanfbe732e2020-01-24 11:26:14 -0800363 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
364 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700365 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700366 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
367 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000368 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800369 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000370 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000371 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800372 << "Should reject motion events with more than MAX_POINTERS pointers.";
373
374 // Rejects motion events with invalid pointer ids.
375 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800376 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
377 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700378 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700379 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
380 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000381 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800382 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000383 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000384 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385 << "Should reject motion events with pointer ids less than 0.";
386
387 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800388 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
389 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700390 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700391 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
392 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000393 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800394 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000395 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000396 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800397 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
398
399 // Rejects motion events with duplicate pointer ids.
400 pointerProperties[0].id = 1;
401 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800402 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
403 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700404 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700405 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
406 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000407 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000409 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000410 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411 << "Should reject motion events with duplicate pointer ids.";
412}
413
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800414/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
415
416TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
417 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000418 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800419 ASSERT_TRUE(mDispatcher->waitForIdle());
420
421 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
422}
423
424TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000425 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
426 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000427 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000428 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800429
430 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
431 args.policyFlags |= POLICY_FLAG_TRUSTED;
432 mFakePolicy->assertNotifySwitchWasCalled(args);
433}
434
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700435namespace {
436
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700437static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700438
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000439class FakeMonitorReceiver {
440public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800441 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
442 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700443 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000444
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700445 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000446
Linnan Li13bf76a2024-05-05 19:18:02 +0800447 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700448 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
449 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000450 }
451
452 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800453 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
454 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000455 }
456
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700457 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000458
Linnan Li13bf76a2024-05-05 19:18:02 +0800459 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
461 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000462 }
463
Linnan Li13bf76a2024-05-05 19:18:02 +0800464 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
466 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000467 }
468
Linnan Li13bf76a2024-05-05 19:18:02 +0800469 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700470 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
471 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000472 }
473
Linnan Li13bf76a2024-05-05 19:18:02 +0800474 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700475 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000476 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
477 WithDisplayId(expectedDisplayId),
478 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
479 }
480
481 void consumeMotionPointerDown(int32_t pointerIdx) {
482 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
483 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700484 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700485 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000486 }
487
488 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700489 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000490 }
491
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800492 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000493
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800494 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000495
496private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700497 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000498};
499
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800500static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700501 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700502 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800503 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800504 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000505 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000506 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800507 KeyEvent event;
508 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
509
510 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800511 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000512 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
513 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800514
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800515 if (!allowKeyRepeat) {
516 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
517 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800518 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700519 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800520}
521
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700522static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
523 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700524 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
525 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
526 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700527 if (result != InputEventInjectionResult::TIMED_OUT) {
528 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
529 }
530}
531
Linnan Li13bf76a2024-05-05 19:18:02 +0800532static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700533 InputDispatcher& dispatcher,
534 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000535 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700536}
537
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800538// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
539// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
540// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800541static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700542 InputDispatcher& dispatcher,
543 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000544 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800545 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800547}
548
Linnan Li13bf76a2024-05-05 19:18:02 +0800549static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700550 InputDispatcher& dispatcher,
551 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000552 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700553}
554
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800555static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700556 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700557 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000558 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000559 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700560 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
561 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700562}
563
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800564static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800565 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700566 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700567 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700568 AMOTION_EVENT_INVALID_CURSOR_POSITION},
569 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800570 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000571 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000572 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700573 MotionEventBuilder motionBuilder =
574 MotionEventBuilder(action, source)
575 .displayId(displayId)
576 .eventTime(eventTime)
577 .rawXCursorPosition(cursorPosition.x)
578 .rawYCursorPosition(cursorPosition.y)
579 .pointer(
580 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
581 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
582 motionBuilder.downTime(eventTime);
583 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800584
585 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700586 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
587 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800588}
589
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700590static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800591 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700592 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700593 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700594}
595
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700596static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800597 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800598 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700599 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000600}
601
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700602static NotifyKeyArgs generateKeyArgs(
603 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800604 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
605 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000606 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
607 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
608 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800609
610 return args;
611}
612
Prabir Pradhan678438e2023-04-13 19:32:51 +0000613[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800614 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000615 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800616 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700617 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
618 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
619 }
620
chaviwd1c23182019-12-20 18:44:56 -0800621 PointerProperties pointerProperties[pointerCount];
622 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800623
chaviwd1c23182019-12-20 18:44:56 -0800624 for (size_t i = 0; i < pointerCount; i++) {
625 pointerProperties[i].clear();
626 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700627 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800628
chaviwd1c23182019-12-20 18:44:56 -0800629 pointerCoords[i].clear();
630 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
631 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
632 }
Jackal Guof9696682018-10-05 12:23:23 +0800633
634 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
635 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000636 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
637 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
638 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800639 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000640 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700641 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000642 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800643
644 return args;
645}
646
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800647static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
648 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
649}
650
Linnan Li13bf76a2024-05-05 19:18:02 +0800651static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
652 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800653 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
654}
655
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000656static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
657 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000658 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
659 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800660}
661
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700662} // namespace
663
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800664/**
665 * When a window unexpectedly disposes of its input channel, policy should be notified about the
666 * broken channel.
667 */
668TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
671 "Window that breaks its input channel",
672 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700674 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800675
676 // Window closes its channel, but the window remains.
677 window->destroyReceiver();
678 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
679}
680
Arthur Hungb92218b2018-08-14 12:00:21 +0800681TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700683 sp<FakeWindowHandle> window =
684 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
685 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700689 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
690 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800692
693 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700694 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800695}
696
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800697using InputDispatcherDeathTest = InputDispatcherTest;
698
699/**
700 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
701 * should crash.
702 */
703TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
704 testing::GTEST_FLAG(death_test_style) = "threadsafe";
705 ScopedSilentDeath _silentDeath;
706
707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700708 sp<FakeWindowHandle> window =
709 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
710 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800711 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
712 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
713 "Incorrect WindowInfosUpdate provided");
714}
715
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700716TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700718 sp<FakeWindowHandle> window =
719 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
720 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700721
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700722 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700723 // Inject a MotionEvent to an unknown display.
724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
726 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
728
729 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700730 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700731}
732
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700733/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700734 * Calling onWindowInfosChanged once should not cause any issues.
735 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700736 * called twice.
737 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800738TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700740 sp<FakeWindowHandle> window =
741 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
742 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700743 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700744
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700745 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700747 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
748 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700750
751 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700752 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700753}
754
755/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700756 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700757 */
758TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700760 sp<FakeWindowHandle> window =
761 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
762 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700763 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700765 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700768 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
769 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700771
772 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700773 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700774}
775
Arthur Hungb92218b2018-08-14 12:00:21 +0800776// The foreground window should receive the first touch down event.
777TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700779 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
780 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000781 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700782 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
783 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700785 mDispatcher->onWindowInfosChanged(
786 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700788 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
789 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800791
792 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700793 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800794 windowSecond->assertNoEvents();
795}
796
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000797/**
798 * Two windows: A top window, and a wallpaper behind the window.
799 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
800 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800801 * 1. foregroundWindow <-- dup touch to wallpaper
802 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000803 */
804TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
806 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700807 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
808 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800809 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000810 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700811 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
812 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800813 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000814
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700815 mDispatcher->onWindowInfosChanged(
816 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800818 injectMotionEvent(*mDispatcher,
819 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
820 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
821 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
823
824 // Both foreground window and its wallpaper should receive the touch down
825 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700826 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000827
828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800829 injectMotionEvent(*mDispatcher,
830 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
831 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
832 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
834
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800835 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700836 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000837
838 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700839 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000840 foregroundWindow->consumeMotionCancel();
841 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700842 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000843}
844
845/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846 * Two fingers down on the window, and lift off the first finger.
847 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
848 * contains a single pointer.
849 */
850TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700852 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
853 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800854
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800856 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
858 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
859 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800860 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000861 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
862 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
863 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
864 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800865 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000866 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
867 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
868 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
869 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800870 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
871 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
872 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
873
874 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700875 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800876 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
877 window->consumeMotionEvent(
878 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
879}
880
881/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800882 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
883 * with the following differences:
884 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
885 * clean up the connection.
886 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
887 * Ensure that there's no crash in the dispatcher.
888 */
889TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
891 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700892 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
893 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800894 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800895 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700896 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
897 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800898 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800899
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700900 mDispatcher->onWindowInfosChanged(
901 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700903 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
904 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
906
907 // Both foreground window and its wallpaper should receive the touch down
908 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700909 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800910
911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700912 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700913 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
915
916 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700917 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800918
919 // Wallpaper closes its channel, but the window remains.
920 wallpaperWindow->destroyReceiver();
921 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
922
923 // Now the foreground window goes away, but the wallpaper stays, even though its channel
924 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700925 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800926 foregroundWindow->consumeMotionCancel();
927}
928
Linnan Li72352222024-04-12 18:55:57 +0800929/**
930 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
931 * down event to the left window. Device B sends a down event to the right window. Next, the right
932 * window disappears. Both the right window and its wallpaper window should receive cancel event.
933 * The left window and its wallpaper window should not receive any events.
934 */
935TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
937 sp<FakeWindowHandle> leftForegroundWindow =
938 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700939 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800940 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
941 leftForegroundWindow->setDupTouchToWallpaper(true);
942 sp<FakeWindowHandle> leftWallpaperWindow =
943 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700944 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800945 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
946 leftWallpaperWindow->setIsWallpaper(true);
947
948 sp<FakeWindowHandle> rightForegroundWindow =
949 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700950 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800951 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
952 rightForegroundWindow->setDupTouchToWallpaper(true);
953 sp<FakeWindowHandle> rightWallpaperWindow =
954 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700955 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800956 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
957 rightWallpaperWindow->setIsWallpaper(true);
958
959 mDispatcher->onWindowInfosChanged(
960 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
961 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
962 {},
963 0,
964 0});
965
966 const DeviceId deviceA = 9;
967 const DeviceId deviceB = 3;
968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
969 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
970 .deviceId(deviceA)
971 .build());
972 leftForegroundWindow->consumeMotionEvent(
973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
974 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
975 WithDeviceId(deviceA),
976 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
977
978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
979 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
980 .deviceId(deviceB)
981 .build());
982 rightForegroundWindow->consumeMotionEvent(
983 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
984 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
985 WithDeviceId(deviceB),
986 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
987
988 // Now right foreground window disappears, but right wallpaper window remains.
989 mDispatcher->onWindowInfosChanged(
990 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
991 *rightWallpaperWindow->getInfo()},
992 {},
993 0,
994 0});
995
996 // Left foreground window and left wallpaper window still exist, and should not receive any
997 // events.
998 leftForegroundWindow->assertNoEvents();
999 leftWallpaperWindow->assertNoEvents();
1000 // Since right foreground window disappeared, right wallpaper window and right foreground window
1001 // should receive cancel events.
1002 rightForegroundWindow->consumeMotionEvent(
1003 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1004 rightWallpaperWindow->consumeMotionEvent(
1005 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1006 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1007}
1008
1009/**
1010 * Three windows arranged horizontally and without any overlap. Every window has a
1011 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1012 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1013 * Next, device B sends move event to the right window. Touch for device B should slip from the
1014 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1015 * The middle window and its wallpaper window should receive a cancel event. The left window should
1016 * not receive any events. If device B continues to report events, the right window and its
1017 * wallpaper window should receive remaining events.
1018 */
1019TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1021 sp<FakeWindowHandle> leftForegroundWindow =
1022 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001023 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001024 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1025 leftForegroundWindow->setDupTouchToWallpaper(true);
1026 sp<FakeWindowHandle> leftWallpaperWindow =
1027 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001028 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001029 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1030 leftWallpaperWindow->setIsWallpaper(true);
1031
1032 sp<FakeWindowHandle> middleForegroundWindow =
1033 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001034 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001035 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1036 middleForegroundWindow->setDupTouchToWallpaper(true);
1037 middleForegroundWindow->setSlippery(true);
1038 sp<FakeWindowHandle> middleWallpaperWindow =
1039 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001040 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001041 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1042 middleWallpaperWindow->setIsWallpaper(true);
1043
1044 sp<FakeWindowHandle> rightForegroundWindow =
1045 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001046 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001047 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1048 rightForegroundWindow->setDupTouchToWallpaper(true);
1049 sp<FakeWindowHandle> rightWallpaperWindow =
1050 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001051 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001052 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1053 rightWallpaperWindow->setIsWallpaper(true);
1054
1055 mDispatcher->onWindowInfosChanged(
1056 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1057 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1058 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1059 {},
1060 0,
1061 0});
1062
1063 const DeviceId deviceA = 9;
1064 const DeviceId deviceB = 3;
1065 // Device A sends a DOWN event to the left window
1066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1067 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1068 .deviceId(deviceA)
1069 .build());
1070 leftForegroundWindow->consumeMotionEvent(
1071 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1072 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1073 WithDeviceId(deviceA),
1074 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1075 // Device B sends a DOWN event to the middle window
1076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1077 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1078 .deviceId(deviceB)
1079 .build());
1080 middleForegroundWindow->consumeMotionEvent(
1081 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1082 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1083 WithDeviceId(deviceB),
1084 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1085 // Move the events of device B to the top of the right window.
1086 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1087 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1088 .deviceId(deviceB)
1089 .build());
1090 middleForegroundWindow->consumeMotionEvent(
1091 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1092 middleWallpaperWindow->consumeMotionEvent(
1093 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1094 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1095 rightForegroundWindow->consumeMotionEvent(
1096 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1097 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1098 WithDeviceId(deviceB),
1099 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1100 // Make sure the window on the right can receive the remaining events.
1101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1102 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1103 .deviceId(deviceB)
1104 .build());
1105 leftForegroundWindow->assertNoEvents();
1106 leftWallpaperWindow->assertNoEvents();
1107 middleForegroundWindow->assertNoEvents();
1108 middleWallpaperWindow->assertNoEvents();
1109 rightForegroundWindow->consumeMotionEvent(
1110 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1111 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1112 WithDeviceId(deviceB),
1113 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1114}
1115
1116/**
1117 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1118 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1119 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1120 * event to the middle window and then touch is transferred from the middle window to the right
1121 * window. The right window and its wallpaper window should receive a down event. The middle window
1122 * and its wallpaper window should receive a cancel event. The left window should not receive any
1123 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1124 */
1125TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1127 sp<FakeWindowHandle> leftForegroundWindow =
1128 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001129 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001130 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1131 leftForegroundWindow->setDupTouchToWallpaper(true);
1132 sp<FakeWindowHandle> leftWallpaperWindow =
1133 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001134 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001135 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1136 leftWallpaperWindow->setIsWallpaper(true);
1137
1138 sp<FakeWindowHandle> middleForegroundWindow =
1139 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001140 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001141 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1142 middleForegroundWindow->setDupTouchToWallpaper(true);
1143 sp<FakeWindowHandle> middleWallpaperWindow =
1144 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001145 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001146 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1147 middleWallpaperWindow->setIsWallpaper(true);
1148
1149 sp<FakeWindowHandle> rightForegroundWindow =
1150 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001151 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001152 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1153 rightForegroundWindow->setDupTouchToWallpaper(true);
1154 sp<FakeWindowHandle> rightWallpaperWindow =
1155 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001156 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001157 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1158 rightWallpaperWindow->setIsWallpaper(true);
1159
1160 mDispatcher->onWindowInfosChanged(
1161 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1162 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1163 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1164 {},
1165 0,
1166 0});
1167
1168 const DeviceId deviceA = 9;
1169 const DeviceId deviceB = 3;
1170 // Device A touch down on the left window
1171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1172 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1173 .deviceId(deviceA)
1174 .build());
1175 leftForegroundWindow->consumeMotionEvent(
1176 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1177 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1178 WithDeviceId(deviceA),
1179 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1180 // Device B touch down on the middle window
1181 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1182 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1183 .deviceId(deviceB)
1184 .build());
1185 middleForegroundWindow->consumeMotionEvent(
1186 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1187 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1188 WithDeviceId(deviceB),
1189 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1190
1191 // Transfer touch from the middle window to the right window.
1192 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1193 rightForegroundWindow->getToken()));
1194
1195 middleForegroundWindow->consumeMotionEvent(
1196 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1197 middleWallpaperWindow->consumeMotionEvent(
1198 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1199 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1200 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1201 WithDeviceId(deviceB),
1202 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1203 rightWallpaperWindow->consumeMotionEvent(
1204 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1205 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1206
1207 // Make sure the right window can receive the remaining events.
1208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1209 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1210 .deviceId(deviceB)
1211 .build());
1212 leftForegroundWindow->assertNoEvents();
1213 leftWallpaperWindow->assertNoEvents();
1214 middleForegroundWindow->assertNoEvents();
1215 middleWallpaperWindow->assertNoEvents();
1216 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1217 WithDeviceId(deviceB),
1218 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1219 rightWallpaperWindow->consumeMotionEvent(
1220 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1221 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1222}
1223
Arthur Hungc539dbb2022-12-08 07:45:36 +00001224class ShouldSplitTouchFixture : public InputDispatcherTest,
1225 public ::testing::WithParamInterface<bool> {};
1226INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1227 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001228/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001229 * A single window that receives touch (on top), and a wallpaper window underneath it.
1230 * The top window gets a multitouch gesture.
1231 * Ensure that wallpaper gets the same gesture.
1232 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001233TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001235 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001236 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1237 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001238 foregroundWindow->setDupTouchToWallpaper(true);
1239 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001240
1241 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001242 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1243 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001244 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001245
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001246 mDispatcher->onWindowInfosChanged(
1247 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001248
1249 // Touch down on top window
1250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001251 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1252 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1254
1255 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001256 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001257 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001258
1259 // Second finger down on the top window
1260 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001261 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001262 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001263 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1264 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001265 .build();
1266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001267 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001268 InputEventInjectionSync::WAIT_FOR_RESULT))
1269 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001270 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001271 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001272 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001273
1274 const MotionEvent secondFingerUpEvent =
1275 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001276 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001277 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001278 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1279 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001280 .build();
1281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001283 InputEventInjectionSync::WAIT_FOR_RESULT))
1284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001285 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1286 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1287 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1288 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1289 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001290
1291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001292 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001293 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1294 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001295 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001296 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001297 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001298 .x(100)
1299 .y(100))
1300 .build(),
1301 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001303 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1304 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001305}
1306
1307/**
1308 * Two windows: a window on the left and window on the right.
1309 * A third window, wallpaper, is behind both windows, and spans both top windows.
1310 * The first touch down goes to the left window. A second pointer touches down on the right window.
1311 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1312 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1313 * ACTION_POINTER_DOWN(1).
1314 */
1315TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001317 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1318 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001319 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001320 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001321
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001322 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1323 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001324 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001325 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001326
1327 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001328 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1329 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001330 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001331 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001332
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001333 mDispatcher->onWindowInfosChanged(
1334 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1335 {},
1336 0,
1337 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001338
1339 // Touch down on left window
1340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001341 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1342 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1344
1345 // Both foreground window and its wallpaper should receive the touch down
1346 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001347 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001348
1349 // Second finger down on the right window
1350 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001351 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001352 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001353 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1354 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001355 .build();
1356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001357 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001358 InputEventInjectionSync::WAIT_FOR_RESULT))
1359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1360
1361 leftWindow->consumeMotionMove();
1362 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001363 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1364 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001365 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001366
1367 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001368 mDispatcher->onWindowInfosChanged(
1369 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001370 leftWindow->consumeMotionCancel();
1371 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001372 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001373
1374 // The pointer that's still down on the right window moves, and goes to the right window only.
1375 // As far as the dispatcher's concerned though, both pointers are still present.
1376 const MotionEvent secondFingerMoveEvent =
1377 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1378 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001379 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001381 .build();
1382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001383 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001384 InputEventInjectionSync::WAIT_FOR_RESULT));
1385 rightWindow->consumeMotionMove();
1386
1387 leftWindow->assertNoEvents();
1388 rightWindow->assertNoEvents();
1389 wallpaperWindow->assertNoEvents();
1390}
1391
Arthur Hungc539dbb2022-12-08 07:45:36 +00001392/**
1393 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1394 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1395 * The right window should receive ACTION_DOWN.
1396 */
1397TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001399 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1400 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001401 leftWindow->setFrame(Rect(0, 0, 200, 200));
1402 leftWindow->setDupTouchToWallpaper(true);
1403 leftWindow->setSlippery(true);
1404
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001405 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1406 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001407 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001408
1409 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001410 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1411 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001412 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001413
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001414 mDispatcher->onWindowInfosChanged(
1415 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1416 {},
1417 0,
1418 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001419
Arthur Hungc539dbb2022-12-08 07:45:36 +00001420 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001422 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1423 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001425
1426 // Both foreground window and its wallpaper should receive the touch down
1427 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001428 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001429
Arthur Hungc539dbb2022-12-08 07:45:36 +00001430 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001432 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001433 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1435
Arthur Hungc539dbb2022-12-08 07:45:36 +00001436 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001437 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1438 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001439}
1440
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001441/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001442 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1443 * interactive, it might stop sending this flag.
1444 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1445 * to have a consistent input stream.
1446 *
1447 * Test procedure:
1448 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1449 * DOWN (new gesture).
1450 *
1451 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1452 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1453 *
1454 * We technically just need a single window here, but we are using two windows (spy on top and a
1455 * regular window below) to emulate the actual situation where it happens on the device.
1456 */
1457TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1458 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001459 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1460 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001461 spyWindow->setFrame(Rect(0, 0, 200, 200));
1462 spyWindow->setTrustedOverlay(true);
1463 spyWindow->setSpy(true);
1464
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001465 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1466 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001467 window->setFrame(Rect(0, 0, 200, 200));
1468
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001469 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001470 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001471
1472 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001473 mDispatcher->notifyMotion(
1474 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1475 .deviceId(touchDeviceId)
1476 .policyFlags(DEFAULT_POLICY_FLAGS)
1477 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1478 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001479
Prabir Pradhan678438e2023-04-13 19:32:51 +00001480 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1481 .deviceId(touchDeviceId)
1482 .policyFlags(DEFAULT_POLICY_FLAGS)
1483 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1484 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1485 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001486 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1487 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1488 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1489 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1490
1491 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001492 mDispatcher->notifyMotion(
1493 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1494 .deviceId(touchDeviceId)
1495 .policyFlags(0)
1496 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1497 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1498 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001499 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1500 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1501
1502 // We don't need to reset the device to reproduce the issue, but the reset event typically
1503 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001504 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001505
1506 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001507 mDispatcher->notifyMotion(
1508 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1509 .deviceId(touchDeviceId)
1510 .policyFlags(DEFAULT_POLICY_FLAGS)
1511 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1512 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001513 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1514 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1515
1516 // No more events
1517 spyWindow->assertNoEvents();
1518 window->assertNoEvents();
1519}
1520
1521/**
Linnan Li907ae732023-09-05 17:14:21 +08001522 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1523 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1524 * interactive, it might stop sending this flag.
1525 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1526 * the consistency of the hover event in this case.
1527 *
1528 * Test procedure:
1529 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1530 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1531 *
1532 * We expect to receive two full streams of hover events.
1533 */
1534TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1535 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1536
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001537 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1538 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001539 window->setFrame(Rect(0, 0, 300, 300));
1540
1541 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1542
1543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1544 .policyFlags(DEFAULT_POLICY_FLAGS)
1545 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1546 .build());
1547 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1548
1549 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1550 .policyFlags(DEFAULT_POLICY_FLAGS)
1551 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1552 .build());
1553 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1554
1555 // Send hover exit without the default policy flags.
1556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1557 .policyFlags(0)
1558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1559 .build());
1560
1561 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1562
1563 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1564 // right event.
1565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1566 .policyFlags(DEFAULT_POLICY_FLAGS)
1567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1568 .build());
1569 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1570
1571 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1572 .policyFlags(DEFAULT_POLICY_FLAGS)
1573 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1574 .build());
1575 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1576
1577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1578 .policyFlags(DEFAULT_POLICY_FLAGS)
1579 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1580 .build());
1581 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1582}
1583
1584/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001585 * Two windows: a window on the left and a window on the right.
1586 * Mouse is hovered from the right window into the left window.
1587 * Next, we tap on the left window, where the cursor was last seen.
1588 * The second tap is done onto the right window.
1589 * The mouse and tap are from two different devices.
1590 * We technically don't need to set the downtime / eventtime for these events, but setting these
1591 * explicitly helps during debugging.
1592 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1593 * In the buggy implementation, a tap on the right window would cause a crash.
1594 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001595TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1596 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1597
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001599 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1600 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001601 leftWindow->setFrame(Rect(0, 0, 200, 200));
1602
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001603 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1604 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001605 rightWindow->setFrame(Rect(200, 0, 400, 200));
1606
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001607 mDispatcher->onWindowInfosChanged(
1608 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001609 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1610 // stale.
1611 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1612 const int32_t mouseDeviceId = 6;
1613 const int32_t touchDeviceId = 4;
1614 // Move the cursor from right
1615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001616 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001617 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1618 AINPUT_SOURCE_MOUSE)
1619 .deviceId(mouseDeviceId)
1620 .downTime(baseTime + 10)
1621 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001622 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001623 .build()));
1624 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1625
1626 // .. to the left window
1627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001628 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001629 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1630 AINPUT_SOURCE_MOUSE)
1631 .deviceId(mouseDeviceId)
1632 .downTime(baseTime + 10)
1633 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001634 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001635 .build()));
1636 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1637 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1638 // Now tap the left window
1639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001640 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001641 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1642 AINPUT_SOURCE_TOUCHSCREEN)
1643 .deviceId(touchDeviceId)
1644 .downTime(baseTime + 40)
1645 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001646 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001647 .build()));
1648 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1649 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1650
1651 // release tap
1652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001653 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001654 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1655 AINPUT_SOURCE_TOUCHSCREEN)
1656 .deviceId(touchDeviceId)
1657 .downTime(baseTime + 40)
1658 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001659 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001660 .build()));
1661 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1662
1663 // Tap the window on the right
1664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001665 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001666 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1667 AINPUT_SOURCE_TOUCHSCREEN)
1668 .deviceId(touchDeviceId)
1669 .downTime(baseTime + 60)
1670 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001671 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001672 .build()));
1673 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1674
1675 // release tap
1676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001677 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001678 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1679 AINPUT_SOURCE_TOUCHSCREEN)
1680 .deviceId(touchDeviceId)
1681 .downTime(baseTime + 60)
1682 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001683 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001684 .build()));
1685 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1686
1687 // No more events
1688 leftWindow->assertNoEvents();
1689 rightWindow->assertNoEvents();
1690}
1691
1692/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001693 * Two windows: a window on the left and a window on the right.
1694 * Mouse is hovered from the right window into the left window.
1695 * Next, we tap on the left window, where the cursor was last seen.
1696 * The second tap is done onto the right window.
1697 * The mouse and tap are from two different devices.
1698 * We technically don't need to set the downtime / eventtime for these events, but setting these
1699 * explicitly helps during debugging.
1700 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1701 * In the buggy implementation, a tap on the right window would cause a crash.
1702 */
1703TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1704 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1705
1706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001707 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1708 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001709 leftWindow->setFrame(Rect(0, 0, 200, 200));
1710
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001711 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1712 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001713 rightWindow->setFrame(Rect(200, 0, 400, 200));
1714
1715 mDispatcher->onWindowInfosChanged(
1716 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1717 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1718 // stale.
1719 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1720 const int32_t mouseDeviceId = 6;
1721 const int32_t touchDeviceId = 4;
1722 // Move the cursor from right
1723 mDispatcher->notifyMotion(
1724 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1725 .deviceId(mouseDeviceId)
1726 .downTime(baseTime + 10)
1727 .eventTime(baseTime + 20)
1728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1729 .build());
1730 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1731
1732 // .. to the left window
1733 mDispatcher->notifyMotion(
1734 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1735 .deviceId(mouseDeviceId)
1736 .downTime(baseTime + 10)
1737 .eventTime(baseTime + 30)
1738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1739 .build());
1740 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1741 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1742 // Now tap the left window
1743 mDispatcher->notifyMotion(
1744 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1745 .deviceId(touchDeviceId)
1746 .downTime(baseTime + 40)
1747 .eventTime(baseTime + 40)
1748 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1749 .build());
1750 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1751
1752 // release tap
1753 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1754 .deviceId(touchDeviceId)
1755 .downTime(baseTime + 40)
1756 .eventTime(baseTime + 50)
1757 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1758 .build());
1759 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1760
1761 // Tap the window on the right
1762 mDispatcher->notifyMotion(
1763 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1764 .deviceId(touchDeviceId)
1765 .downTime(baseTime + 60)
1766 .eventTime(baseTime + 60)
1767 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1768 .build());
1769 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1770
1771 // release tap
1772 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1773 .deviceId(touchDeviceId)
1774 .downTime(baseTime + 60)
1775 .eventTime(baseTime + 70)
1776 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1777 .build());
1778 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1779
1780 // No more events
1781 leftWindow->assertNoEvents();
1782 rightWindow->assertNoEvents();
1783}
1784
1785/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001786 * Start hovering in a window. While this hover is still active, make another window appear on top.
1787 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1788 * While the top window is present, the hovering is stopped.
1789 * Later, hovering gets resumed again.
1790 * Ensure that new hover gesture is handled correctly.
1791 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1792 * to the window that's currently being hovered over.
1793 */
1794TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1797 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001798 window->setFrame(Rect(0, 0, 200, 200));
1799
1800 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001802
1803 // Start hovering in the window
1804 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1805 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1806 .build());
1807 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1808
1809 // Now, an obscuring window appears!
1810 sp<FakeWindowHandle> obscuringWindow =
1811 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001812 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001813 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001814 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1815 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1816 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1817 obscuringWindow->setNoInputChannel(true);
1818 obscuringWindow->setFocusable(false);
1819 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged(
1821 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001822
1823 // While this new obscuring window is present, the hovering is stopped
1824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1825 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1826 .build());
1827 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1828
1829 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001830 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001831
1832 // And a new hover gesture starts.
1833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1834 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1835 .build());
1836 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1837}
1838
1839/**
1840 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1841 * the obscuring window.
1842 */
1843TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001845 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1846 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001847 window->setFrame(Rect(0, 0, 200, 200));
1848
1849 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001850 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001851
1852 // Start hovering in the window
1853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1855 .build());
1856 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1857
1858 // Now, an obscuring window appears!
1859 sp<FakeWindowHandle> obscuringWindow =
1860 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001861 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001862 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001863 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1864 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1865 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1866 obscuringWindow->setNoInputChannel(true);
1867 obscuringWindow->setFocusable(false);
1868 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001869 mDispatcher->onWindowInfosChanged(
1870 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001871
1872 // While this new obscuring window is present, the hovering continues. The event can't go to the
1873 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1875 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1876 .build());
1877 obscuringWindow->assertNoEvents();
1878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1879
1880 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001882
1883 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1884 // so it should generate a HOVER_ENTER
1885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1886 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1887 .build());
1888 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1889
1890 // Now the MOVE should be getting dispatched normally
1891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1892 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1893 .build());
1894 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1895}
1896
1897/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001898 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1899 * events are delivered to the window.
1900 */
1901TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001903 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1904 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001905 window->setFrame(Rect(0, 0, 200, 200));
1906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1907
1908 // Start hovering in the window
1909 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1910 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1911 .build());
1912 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1913
1914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1915 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1916 .build());
1917 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1918
1919 // Scroll with the mouse
1920 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1921 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1922 .build());
1923 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1924}
1925
1926using InputDispatcherMultiDeviceTest = InputDispatcherTest;
1927
1928/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001929 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1930 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001931 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001932TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001933 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001935 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1936 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001937 window->setFrame(Rect(0, 0, 200, 200));
1938
1939 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1940
1941 constexpr int32_t touchDeviceId = 4;
1942 constexpr int32_t stylusDeviceId = 2;
1943
1944 // Stylus down
1945 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1946 .deviceId(stylusDeviceId)
1947 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1948 .build());
1949 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1950
1951 // Touch down
1952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1953 .deviceId(touchDeviceId)
1954 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1955 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001956
1957 // Touch move
1958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1959 .deviceId(touchDeviceId)
1960 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1961 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001962 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001963
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001964 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1966 .deviceId(stylusDeviceId)
1967 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
1968 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001969 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
1970 WithCoords(101, 111)));
1971
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001972 window->assertNoEvents();
1973}
1974
1975/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001976 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1977 * touch is not dropped, because multiple devices are allowed to be active in the same window.
1978 */
1979TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
1980 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001982 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1983 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001984 window->setFrame(Rect(0, 0, 200, 200));
1985
1986 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1987
1988 constexpr int32_t touchDeviceId = 4;
1989 constexpr int32_t stylusDeviceId = 2;
1990
1991 // Stylus down
1992 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1993 .deviceId(stylusDeviceId)
1994 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1995 .build());
1996 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1997
1998 // Touch down
1999 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2000 .deviceId(touchDeviceId)
2001 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2002 .build());
2003 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2004
2005 // Touch move
2006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2007 .deviceId(touchDeviceId)
2008 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2009 .build());
2010 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2011
2012 // Stylus move
2013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2014 .deviceId(stylusDeviceId)
2015 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2016 .build());
2017 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2018 WithCoords(101, 111)));
2019
2020 window->assertNoEvents();
2021}
2022
2023/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002024 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002025 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002026 * Similar test as above, but with added SPY window.
2027 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002028TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002029 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002031 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2032 ui::LogicalDisplayId::DEFAULT);
2033 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2034 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002035 spyWindow->setFrame(Rect(0, 0, 200, 200));
2036 spyWindow->setTrustedOverlay(true);
2037 spyWindow->setSpy(true);
2038 window->setFrame(Rect(0, 0, 200, 200));
2039
2040 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2041
2042 constexpr int32_t touchDeviceId = 4;
2043 constexpr int32_t stylusDeviceId = 2;
2044
2045 // Stylus down
2046 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2047 .deviceId(stylusDeviceId)
2048 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2049 .build());
2050 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2051 spyWindow->consumeMotionEvent(
2052 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2053
2054 // Touch down
2055 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2056 .deviceId(touchDeviceId)
2057 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2058 .build());
2059
2060 // Touch move
2061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2062 .deviceId(touchDeviceId)
2063 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2064 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002065
2066 // Touch is ignored because stylus is already down
2067
2068 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2070 .deviceId(stylusDeviceId)
2071 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2072 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002073 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2074 WithCoords(101, 111)));
2075 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2076 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002077
2078 window->assertNoEvents();
2079 spyWindow->assertNoEvents();
2080}
2081
2082/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002083 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2084 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2085 * Similar test as above, but with added SPY window.
2086 */
2087TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2088 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002090 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2091 ui::LogicalDisplayId::DEFAULT);
2092 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2093 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002094 spyWindow->setFrame(Rect(0, 0, 200, 200));
2095 spyWindow->setTrustedOverlay(true);
2096 spyWindow->setSpy(true);
2097 window->setFrame(Rect(0, 0, 200, 200));
2098
2099 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2100
2101 constexpr int32_t touchDeviceId = 4;
2102 constexpr int32_t stylusDeviceId = 2;
2103
2104 // Stylus down
2105 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2106 .deviceId(stylusDeviceId)
2107 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2108 .build());
2109 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2110 spyWindow->consumeMotionEvent(
2111 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2112
2113 // Touch down
2114 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2115 .deviceId(touchDeviceId)
2116 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2117 .build());
2118 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2119 spyWindow->consumeMotionEvent(
2120 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2121
2122 // Touch move
2123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2124 .deviceId(touchDeviceId)
2125 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2126 .build());
2127 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2128 spyWindow->consumeMotionEvent(
2129 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2130
2131 // Subsequent stylus movements are delivered correctly
2132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2133 .deviceId(stylusDeviceId)
2134 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2135 .build());
2136 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2137 WithCoords(101, 111)));
2138 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2139 WithCoords(101, 111)));
2140
2141 window->assertNoEvents();
2142 spyWindow->assertNoEvents();
2143}
2144
2145/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002146 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002147 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002148 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002149TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002150 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002152 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2153 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002154 window->setFrame(Rect(0, 0, 200, 200));
2155
2156 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2157
2158 constexpr int32_t touchDeviceId = 4;
2159 constexpr int32_t stylusDeviceId = 2;
2160
2161 // Stylus down on the window
2162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2163 .deviceId(stylusDeviceId)
2164 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2165 .build());
2166 window->consumeMotionEvent(
2167 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2168
2169 // Touch down on window
2170 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2171 .deviceId(touchDeviceId)
2172 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2173 .build());
2174 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2175 .deviceId(touchDeviceId)
2176 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2177 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002178
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002179 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002180
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002181 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2183 .deviceId(stylusDeviceId)
2184 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2185 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002186 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2187 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002188
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002189 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002190 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2191 .deviceId(touchDeviceId)
2192 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2193 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002194 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002195}
2196
2197/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002198 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2199 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2200 */
2201TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2202 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002204 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2205 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002206 window->setFrame(Rect(0, 0, 200, 200));
2207
2208 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2209
2210 constexpr int32_t touchDeviceId = 4;
2211 constexpr int32_t stylusDeviceId = 2;
2212
2213 // Stylus down on the window
2214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2215 .deviceId(stylusDeviceId)
2216 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2217 .build());
2218 window->consumeMotionEvent(
2219 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2220
2221 // Touch down on window
2222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2223 .deviceId(touchDeviceId)
2224 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2225 .build());
2226 // Touch move on window
2227 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2228 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2229 .deviceId(touchDeviceId)
2230 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2231 .build());
2232 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2233
2234 // Subsequent stylus movements are delivered correctly
2235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2236 .deviceId(stylusDeviceId)
2237 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2238 .build());
2239 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2240 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2241
2242 // and subsequent touches continue to work
2243 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2244 .deviceId(touchDeviceId)
2245 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2246 .build());
2247 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2248 window->assertNoEvents();
2249}
2250
2251/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002252 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002253 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002254 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002255TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002256 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002258 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2259 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002260 window->setFrame(Rect(0, 0, 200, 200));
2261
2262 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2263
2264 constexpr int32_t touchDeviceId = 4;
2265 constexpr int32_t stylusDeviceId = 2;
2266
2267 // Touch down on window
2268 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2269 .deviceId(touchDeviceId)
2270 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2271 .build());
2272 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2273 .deviceId(touchDeviceId)
2274 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2275 .build());
2276 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2277 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2278
2279 // Stylus hover on the window
2280 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2281 .deviceId(stylusDeviceId)
2282 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2283 .build());
2284 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2285 .deviceId(stylusDeviceId)
2286 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2287 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002288 // Stylus hover movement causes touch to be canceled
2289 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2290 WithCoords(141, 146)));
2291 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2292 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2293 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2294 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002295
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002296 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002297 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2298 .deviceId(touchDeviceId)
2299 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2300 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002301
2302 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002303}
2304
2305/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002306 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2307 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2308 */
2309TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2310 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2311 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002312 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2313 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002314 window->setFrame(Rect(0, 0, 200, 200));
2315
2316 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2317
2318 constexpr int32_t touchDeviceId = 4;
2319 constexpr int32_t stylusDeviceId = 2;
2320
2321 // Touch down on window
2322 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2323 .deviceId(touchDeviceId)
2324 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2325 .build());
2326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2327 .deviceId(touchDeviceId)
2328 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2329 .build());
2330 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2331 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2332
2333 // Stylus hover on the window
2334 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2335 .deviceId(stylusDeviceId)
2336 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2337 .build());
2338 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2339 .deviceId(stylusDeviceId)
2340 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2341 .build());
2342 // Stylus hover movement is received normally
2343 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2344 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2345 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2346 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2347
2348 // Subsequent touch movements also work
2349 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2350 .deviceId(touchDeviceId)
2351 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2352 .build());
2353 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2354 WithCoords(142, 147)));
2355
2356 window->assertNoEvents();
2357}
2358
2359/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002360 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2361 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2362 * become active.
2363 */
2364TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002365 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002367 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2368 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002369 window->setFrame(Rect(0, 0, 200, 200));
2370
2371 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2372
2373 constexpr int32_t stylusDeviceId1 = 3;
2374 constexpr int32_t stylusDeviceId2 = 5;
2375
2376 // Touch down on window
2377 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2378 .deviceId(stylusDeviceId1)
2379 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2380 .build());
2381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2382 .deviceId(stylusDeviceId1)
2383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2384 .build());
2385 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2386 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2387
2388 // Second stylus down
2389 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2390 .deviceId(stylusDeviceId2)
2391 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2392 .build());
2393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2394 .deviceId(stylusDeviceId2)
2395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2396 .build());
2397
2398 // First stylus is canceled, second one takes over.
2399 window->consumeMotionEvent(
2400 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2401 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2402 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2403
2404 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2405 .deviceId(stylusDeviceId1)
2406 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2407 .build());
2408 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002409 window->assertNoEvents();
2410}
2411
2412/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002413 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2414 * both stylus devices can function simultaneously.
2415 */
2416TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2417 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002419 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2420 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002421 window->setFrame(Rect(0, 0, 200, 200));
2422
2423 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2424
2425 constexpr int32_t stylusDeviceId1 = 3;
2426 constexpr int32_t stylusDeviceId2 = 5;
2427
2428 // Touch down on window
2429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2430 .deviceId(stylusDeviceId1)
2431 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2432 .build());
2433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2434 .deviceId(stylusDeviceId1)
2435 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2436 .build());
2437 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2439
2440 // Second stylus down
2441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2442 .deviceId(stylusDeviceId2)
2443 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2444 .build());
2445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2446 .deviceId(stylusDeviceId2)
2447 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2448 .build());
2449 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2450 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2451
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2453 .deviceId(stylusDeviceId1)
2454 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2455 .build());
2456 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2457 window->assertNoEvents();
2458}
2459
2460/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002461 * One window. Touch down on the window. Then, stylus down on the window from another device.
2462 * Ensure that is canceled, because stylus down should be preferred over touch.
2463 */
2464TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002465 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002467 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2468 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002469 window->setFrame(Rect(0, 0, 200, 200));
2470
2471 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2472
2473 constexpr int32_t touchDeviceId = 4;
2474 constexpr int32_t stylusDeviceId = 2;
2475
2476 // Touch down on window
2477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2478 .deviceId(touchDeviceId)
2479 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2480 .build());
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2482 .deviceId(touchDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2486 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2487
2488 // Stylus down on the window
2489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2490 .deviceId(stylusDeviceId)
2491 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2492 .build());
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2494 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2495
2496 // Subsequent stylus movements are delivered correctly
2497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2498 .deviceId(stylusDeviceId)
2499 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2500 .build());
2501 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2502 WithCoords(101, 111)));
2503}
2504
2505/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002506 * One window. Touch down on the window. Then, stylus down on the window from another device.
2507 * Ensure that both touch and stylus are functioning independently.
2508 */
2509TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2510 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002512 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2513 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002514 window->setFrame(Rect(0, 0, 200, 200));
2515
2516 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2517
2518 constexpr int32_t touchDeviceId = 4;
2519 constexpr int32_t stylusDeviceId = 2;
2520
2521 // Touch down on window
2522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2523 .deviceId(touchDeviceId)
2524 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2525 .build());
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2527 .deviceId(touchDeviceId)
2528 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2529 .build());
2530 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2531 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2532
2533 // Stylus down on the window
2534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2535 .deviceId(stylusDeviceId)
2536 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2537 .build());
2538 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2539
2540 // Subsequent stylus movements are delivered correctly
2541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2542 .deviceId(stylusDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2544 .build());
2545 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2546 WithCoords(101, 111)));
2547
2548 // Touch continues to work too
2549 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2550 .deviceId(touchDeviceId)
2551 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2552 .build());
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2554}
2555
2556/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002557 * Two windows: a window on the left and a window on the right.
2558 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2559 * down. Then, on the left window, also place second touch pointer down.
2560 * This test tries to reproduce a crash.
2561 * In the buggy implementation, second pointer down on the left window would cause a crash.
2562 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002563TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2564 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002566 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2567 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002568 leftWindow->setFrame(Rect(0, 0, 200, 200));
2569
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002570 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2571 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002572 rightWindow->setFrame(Rect(200, 0, 400, 200));
2573
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002574 mDispatcher->onWindowInfosChanged(
2575 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002576
2577 const int32_t touchDeviceId = 4;
2578 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002579
2580 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2582 .deviceId(mouseDeviceId)
2583 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2584 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002585 leftWindow->consumeMotionEvent(
2586 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2587
2588 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2590 .deviceId(mouseDeviceId)
2591 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2592 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2593 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002594
2595 leftWindow->consumeMotionEvent(
2596 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2597 leftWindow->consumeMotionEvent(
2598 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2599
Prabir Pradhan678438e2023-04-13 19:32:51 +00002600 mDispatcher->notifyMotion(
2601 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2602 .deviceId(mouseDeviceId)
2603 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2604 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2605 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2606 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002607 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2608
2609 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2611 .deviceId(touchDeviceId)
2612 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2613 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002614 leftWindow->assertNoEvents();
2615
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002616 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2617
2618 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002619 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2620 .deviceId(touchDeviceId)
2621 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2622 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2623 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002624 // Since this is now a new splittable pointer going down on the left window, and it's coming
2625 // from a different device, the current gesture in the left window (pointer down) should first
2626 // be canceled.
2627 leftWindow->consumeMotionEvent(
2628 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002629 leftWindow->consumeMotionEvent(
2630 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2631 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2632 // current implementation.
2633 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2634 rightWindow->consumeMotionEvent(
2635 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2636
2637 leftWindow->assertNoEvents();
2638 rightWindow->assertNoEvents();
2639}
2640
2641/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002642 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002643 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2644 * down. Then, on the left window, also place second touch pointer down.
2645 * This test tries to reproduce a crash.
2646 * In the buggy implementation, second pointer down on the left window would cause a crash.
2647 */
2648TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2649 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002651 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2652 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002653 leftWindow->setFrame(Rect(0, 0, 200, 200));
2654
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002655 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2656 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002657 rightWindow->setFrame(Rect(200, 0, 400, 200));
2658
2659 mDispatcher->onWindowInfosChanged(
2660 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2661
2662 const int32_t touchDeviceId = 4;
2663 const int32_t mouseDeviceId = 6;
2664
2665 // Start hovering over the left window
2666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2667 .deviceId(mouseDeviceId)
2668 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2669 .build());
2670 leftWindow->consumeMotionEvent(
2671 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2672
2673 // Mouse down on left window
2674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2675 .deviceId(mouseDeviceId)
2676 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2677 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2678 .build());
2679
2680 leftWindow->consumeMotionEvent(
2681 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2682 leftWindow->consumeMotionEvent(
2683 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2684
2685 mDispatcher->notifyMotion(
2686 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2687 .deviceId(mouseDeviceId)
2688 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2689 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2690 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2691 .build());
2692 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2693
2694 // First touch pointer down on right window
2695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2696 .deviceId(touchDeviceId)
2697 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2698 .build());
2699 leftWindow->assertNoEvents();
2700
2701 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2702
2703 // Second touch pointer down on left window
2704 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2705 .deviceId(touchDeviceId)
2706 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2707 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2708 .build());
2709 // Since this is now a new splittable pointer going down on the left window, and it's coming
2710 // from a different device, it will be split and delivered to left window separately.
2711 leftWindow->consumeMotionEvent(
2712 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2713 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2714 // current implementation.
2715 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2716 rightWindow->consumeMotionEvent(
2717 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2718
2719 leftWindow->assertNoEvents();
2720 rightWindow->assertNoEvents();
2721}
2722
2723/**
2724 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002725 * Mouse is hovered on the left window and stylus is hovered on the right window.
2726 */
2727TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002729 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2730 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002731 leftWindow->setFrame(Rect(0, 0, 200, 200));
2732
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002733 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2734 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002735 rightWindow->setFrame(Rect(200, 0, 400, 200));
2736
2737 mDispatcher->onWindowInfosChanged(
2738 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2739
2740 const int32_t stylusDeviceId = 3;
2741 const int32_t mouseDeviceId = 6;
2742
2743 // Start hovering over the left window
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2745 .deviceId(mouseDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2747 .build());
2748 leftWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2750
2751 // Stylus hovered on right window
2752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2753 .deviceId(stylusDeviceId)
2754 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2755 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002756 rightWindow->consumeMotionEvent(
2757 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2758
2759 // Subsequent HOVER_MOVE events are dispatched correctly.
2760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2761 .deviceId(mouseDeviceId)
2762 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2763 .build());
2764 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002765 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002766
2767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2768 .deviceId(stylusDeviceId)
2769 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2770 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002771 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002772 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002773
2774 leftWindow->assertNoEvents();
2775 rightWindow->assertNoEvents();
2776}
2777
2778/**
2779 * Three windows: a window on the left and a window on the right.
2780 * And a spy window that's positioned above all of them.
2781 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2782 * Check the stream that's received by the spy.
2783 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002784TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2785 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2787
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002788 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2789 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002790 spyWindow->setFrame(Rect(0, 0, 400, 400));
2791 spyWindow->setTrustedOverlay(true);
2792 spyWindow->setSpy(true);
2793
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002794 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2795 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002796 leftWindow->setFrame(Rect(0, 0, 200, 200));
2797
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002798 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2799 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002800
2801 rightWindow->setFrame(Rect(200, 0, 400, 200));
2802
2803 mDispatcher->onWindowInfosChanged(
2804 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2805
2806 const int32_t stylusDeviceId = 1;
2807 const int32_t touchDeviceId = 2;
2808
2809 // Stylus down on the left window
2810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2811 .deviceId(stylusDeviceId)
2812 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2813 .build());
2814 leftWindow->consumeMotionEvent(
2815 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2816 spyWindow->consumeMotionEvent(
2817 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2818
2819 // Touch down on the right window
2820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2821 .deviceId(touchDeviceId)
2822 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2823 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002824 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002825 rightWindow->consumeMotionEvent(
2826 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002827
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002828 // Spy window does not receive touch events, because stylus events take precedence, and it
2829 // already has an active stylus gesture.
2830
2831 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2833 .deviceId(stylusDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2835 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002836 leftWindow->consumeMotionEvent(
2837 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2838 spyWindow->consumeMotionEvent(
2839 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002840
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002841 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2843 .deviceId(touchDeviceId)
2844 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2845 .build());
2846 rightWindow->consumeMotionEvent(
2847 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002848
2849 spyWindow->assertNoEvents();
2850 leftWindow->assertNoEvents();
2851 rightWindow->assertNoEvents();
2852}
2853
2854/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002855 * Three windows: a window on the left and a window on the right.
2856 * And a spy window that's positioned above all of them.
2857 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2858 * Check the stream that's received by the spy.
2859 */
2860TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2861 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2863
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002864 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2865 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002866 spyWindow->setFrame(Rect(0, 0, 400, 400));
2867 spyWindow->setTrustedOverlay(true);
2868 spyWindow->setSpy(true);
2869
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002870 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2871 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002872 leftWindow->setFrame(Rect(0, 0, 200, 200));
2873
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002874 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2875 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002876
2877 rightWindow->setFrame(Rect(200, 0, 400, 200));
2878
2879 mDispatcher->onWindowInfosChanged(
2880 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2881
2882 const int32_t stylusDeviceId = 1;
2883 const int32_t touchDeviceId = 2;
2884
2885 // Stylus down on the left window
2886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2887 .deviceId(stylusDeviceId)
2888 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2889 .build());
2890 leftWindow->consumeMotionEvent(
2891 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2892 spyWindow->consumeMotionEvent(
2893 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2894
2895 // Touch down on the right window
2896 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2897 .deviceId(touchDeviceId)
2898 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2899 .build());
2900 leftWindow->assertNoEvents();
2901 rightWindow->consumeMotionEvent(
2902 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2903 spyWindow->consumeMotionEvent(
2904 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2905
2906 // Stylus movements continue. They should be delivered to the left window and to the spy window
2907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2908 .deviceId(stylusDeviceId)
2909 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2910 .build());
2911 leftWindow->consumeMotionEvent(
2912 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2913 spyWindow->consumeMotionEvent(
2914 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2915
2916 // Further touch MOVE events keep going to the right window and to the spy
2917 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2918 .deviceId(touchDeviceId)
2919 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2920 .build());
2921 rightWindow->consumeMotionEvent(
2922 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2923 spyWindow->consumeMotionEvent(
2924 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2925
2926 spyWindow->assertNoEvents();
2927 leftWindow->assertNoEvents();
2928 rightWindow->assertNoEvents();
2929}
2930
2931/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002932 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2933 * both.
2934 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002935 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002936 * At the same time, left and right should be getting independent streams of hovering and touch,
2937 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002938 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002939TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002940 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002941 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2942
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002943 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2944 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002945 spyWindow->setFrame(Rect(0, 0, 400, 400));
2946 spyWindow->setTrustedOverlay(true);
2947 spyWindow->setSpy(true);
2948
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002949 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2950 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002951 leftWindow->setFrame(Rect(0, 0, 200, 200));
2952
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002953 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2954 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002955 rightWindow->setFrame(Rect(200, 0, 400, 200));
2956
2957 mDispatcher->onWindowInfosChanged(
2958 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2959
2960 const int32_t stylusDeviceId = 1;
2961 const int32_t touchDeviceId = 2;
2962
2963 // Stylus hover on the left window
2964 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2965 .deviceId(stylusDeviceId)
2966 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2967 .build());
2968 leftWindow->consumeMotionEvent(
2969 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2970 spyWindow->consumeMotionEvent(
2971 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2972
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002973 // Touch down on the right window. Spy doesn't receive this touch because it already has
2974 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2976 .deviceId(touchDeviceId)
2977 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2978 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002979 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002980 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002981 rightWindow->consumeMotionEvent(
2982 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2983
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002984 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2986 .deviceId(stylusDeviceId)
2987 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2988 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002989 leftWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002991 spyWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002994 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2996 .deviceId(touchDeviceId)
2997 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2998 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002999 rightWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3001
3002 spyWindow->assertNoEvents();
3003 leftWindow->assertNoEvents();
3004 rightWindow->assertNoEvents();
3005}
3006
3007/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003008 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3009 * both.
3010 * Check hover in left window and touch down in the right window.
3011 * At first, spy should receive hover. Next, spy should receive touch.
3012 * At the same time, left and right should be getting independent streams of hovering and touch,
3013 * respectively.
3014 */
3015TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3016 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3018
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003019 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3020 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003021 spyWindow->setFrame(Rect(0, 0, 400, 400));
3022 spyWindow->setTrustedOverlay(true);
3023 spyWindow->setSpy(true);
3024
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003025 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3026 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003027 leftWindow->setFrame(Rect(0, 0, 200, 200));
3028
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003029 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3030 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003031 rightWindow->setFrame(Rect(200, 0, 400, 200));
3032
3033 mDispatcher->onWindowInfosChanged(
3034 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3035
3036 const int32_t stylusDeviceId = 1;
3037 const int32_t touchDeviceId = 2;
3038
3039 // Stylus hover on the left window
3040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3041 .deviceId(stylusDeviceId)
3042 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3043 .build());
3044 leftWindow->consumeMotionEvent(
3045 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3046 spyWindow->consumeMotionEvent(
3047 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3048
3049 // Touch down on the right window.
3050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3051 .deviceId(touchDeviceId)
3052 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3053 .build());
3054 leftWindow->assertNoEvents();
3055 spyWindow->consumeMotionEvent(
3056 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3057 rightWindow->consumeMotionEvent(
3058 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3059
3060 // Stylus movements continue. They should be delivered to the left window and the spy.
3061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3062 .deviceId(stylusDeviceId)
3063 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3064 .build());
3065 leftWindow->consumeMotionEvent(
3066 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3067 spyWindow->consumeMotionEvent(
3068 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3069
3070 // Touch movements continue. They should be delivered to the right window and the spy
3071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3072 .deviceId(touchDeviceId)
3073 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3074 .build());
3075 rightWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3077 spyWindow->consumeMotionEvent(
3078 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3079
3080 spyWindow->assertNoEvents();
3081 leftWindow->assertNoEvents();
3082 rightWindow->assertNoEvents();
3083}
3084
3085/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003086 * On a single window, use two different devices: mouse and touch.
3087 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3088 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3089 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3090 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3091 * represent a new gesture.
3092 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003093TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3094 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003096 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3097 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003098 window->setFrame(Rect(0, 0, 400, 400));
3099
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003100 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101
3102 const int32_t touchDeviceId = 4;
3103 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003104
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003105 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3107 .deviceId(touchDeviceId)
3108 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3109 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003110 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003111 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3112 .deviceId(touchDeviceId)
3113 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3114 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3115 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003116 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003117 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3118 .deviceId(touchDeviceId)
3119 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3120 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3121 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3123 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3124 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3125
3126 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3128 .deviceId(mouseDeviceId)
3129 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3131 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003132
3133 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003134 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003135 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3136
Prabir Pradhan678438e2023-04-13 19:32:51 +00003137 mDispatcher->notifyMotion(
3138 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3139 .deviceId(mouseDeviceId)
3140 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3141 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3142 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3143 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003144 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3145
3146 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003147 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3148 .deviceId(touchDeviceId)
3149 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3150 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3151 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003152 // Since we already canceled this touch gesture, it will be ignored until a completely new
3153 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3154 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3155 // However, mouse movements should continue to work.
3156 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3157 .deviceId(mouseDeviceId)
3158 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3159 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3160 .build());
3161 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3162
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003163 window->assertNoEvents();
3164}
3165
3166/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003167 * On a single window, use two different devices: mouse and touch.
3168 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3169 * Mouse is clicked next, which should not interfere with the touch stream.
3170 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3171 * delivered correctly.
3172 */
3173TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3174 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003176 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3177 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003178 window->setFrame(Rect(0, 0, 400, 400));
3179
3180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3181
3182 const int32_t touchDeviceId = 4;
3183 const int32_t mouseDeviceId = 6;
3184
3185 // First touch pointer down
3186 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3187 .deviceId(touchDeviceId)
3188 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3189 .build());
3190 // Second touch pointer down
3191 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3192 .deviceId(touchDeviceId)
3193 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3194 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3195 .build());
3196 // First touch pointer lifts. The second one remains down
3197 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3198 .deviceId(touchDeviceId)
3199 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3200 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3201 .build());
3202 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3203 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3204 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3205
3206 // Mouse down
3207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3208 .deviceId(mouseDeviceId)
3209 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3210 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3211 .build());
3212
3213 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3214
3215 mDispatcher->notifyMotion(
3216 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3217 .deviceId(mouseDeviceId)
3218 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3219 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3220 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3221 .build());
3222 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3223
3224 // Second touch pointer down.
3225 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3226 .deviceId(touchDeviceId)
3227 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3228 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3229 .build());
3230 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3231 WithPointerCount(2u)));
3232
3233 // Mouse movements should continue to work
3234 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3235 .deviceId(mouseDeviceId)
3236 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3237 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3238 .build());
3239 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3240
3241 window->assertNoEvents();
3242}
3243
3244/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003245 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3246 * the injected event.
3247 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003248TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3249 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003250 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003251 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3252 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003253 window->setFrame(Rect(0, 0, 400, 400));
3254
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003255 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003256
3257 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003258 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3259 // completion.
3260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003261 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003262 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3263 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003264 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003265 .build()));
3266 window->consumeMotionEvent(
3267 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3268
3269 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3270 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3272 .deviceId(touchDeviceId)
3273 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3274 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003275
3276 window->consumeMotionEvent(
3277 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3278 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3279}
3280
3281/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003282 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3283 * parallel to the injected event.
3284 */
3285TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3286 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003288 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3289 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003290 window->setFrame(Rect(0, 0, 400, 400));
3291
3292 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3293
3294 const int32_t touchDeviceId = 4;
3295 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3296 // completion.
3297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3298 injectMotionEvent(*mDispatcher,
3299 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3300 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3301 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3302 .build()));
3303 window->consumeMotionEvent(
3304 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3305
3306 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3307 // allowed through.
3308 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3309 .deviceId(touchDeviceId)
3310 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3311 .build());
3312 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3313}
3314
3315/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003316 * This test is similar to the test above, but the sequence of injected events is different.
3317 *
3318 * Two windows: a window on the left and a window on the right.
3319 * Mouse is hovered over the left window.
3320 * Next, we tap on the left window, where the cursor was last seen.
3321 *
3322 * After that, we inject one finger down onto the right window, and then a second finger down onto
3323 * the left window.
3324 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3325 * window (first), and then another on the left window (second).
3326 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3327 * In the buggy implementation, second finger down on the left window would cause a crash.
3328 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003329TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3330 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003332 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3333 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003334 leftWindow->setFrame(Rect(0, 0, 200, 200));
3335
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003336 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3337 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003338 rightWindow->setFrame(Rect(200, 0, 400, 200));
3339
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003340 mDispatcher->onWindowInfosChanged(
3341 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003342
3343 const int32_t mouseDeviceId = 6;
3344 const int32_t touchDeviceId = 4;
3345 // Hover over the left window. Keep the cursor there.
3346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003348 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3349 AINPUT_SOURCE_MOUSE)
3350 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003352 .build()));
3353 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3354
3355 // Tap on left window
3356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003358 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3359 AINPUT_SOURCE_TOUCHSCREEN)
3360 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003361 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003362 .build()));
3363
3364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003365 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003366 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3367 AINPUT_SOURCE_TOUCHSCREEN)
3368 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003369 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003370 .build()));
3371 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3372 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3373 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3374
3375 // First finger down on right window
3376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003377 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003378 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3379 AINPUT_SOURCE_TOUCHSCREEN)
3380 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003381 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003382 .build()));
3383 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3384
3385 // Second finger down on the left window
3386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003387 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003388 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3389 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003390 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3391 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003392 .build()));
3393 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3394 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3395
3396 // No more events
3397 leftWindow->assertNoEvents();
3398 rightWindow->assertNoEvents();
3399}
3400
3401/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003402 * This test is similar to the test above, but the sequence of injected events is different.
3403 *
3404 * Two windows: a window on the left and a window on the right.
3405 * Mouse is hovered over the left window.
3406 * Next, we tap on the left window, where the cursor was last seen.
3407 *
3408 * After that, we send one finger down onto the right window, and then a second finger down onto
3409 * the left window.
3410 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3411 * window (first), and then another on the left window (second).
3412 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3413 * In the buggy implementation, second finger down on the left window would cause a crash.
3414 */
3415TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3416 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3417 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003418 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3419 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003420 leftWindow->setFrame(Rect(0, 0, 200, 200));
3421
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003422 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3423 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003424 rightWindow->setFrame(Rect(200, 0, 400, 200));
3425
3426 mDispatcher->onWindowInfosChanged(
3427 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3428
3429 const int32_t mouseDeviceId = 6;
3430 const int32_t touchDeviceId = 4;
3431 // Hover over the left window. Keep the cursor there.
3432 mDispatcher->notifyMotion(
3433 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3434 .deviceId(mouseDeviceId)
3435 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3436 .build());
3437 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3438
3439 // Tap on left window
3440 mDispatcher->notifyMotion(
3441 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3442 .deviceId(touchDeviceId)
3443 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3444 .build());
3445
3446 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3447 .deviceId(touchDeviceId)
3448 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3449 .build());
3450 leftWindow->consumeMotionEvent(
3451 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3452 leftWindow->consumeMotionEvent(
3453 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3454
3455 // First finger down on right window
3456 mDispatcher->notifyMotion(
3457 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3458 .deviceId(touchDeviceId)
3459 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3460 .build());
3461 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3462
3463 // Second finger down on the left window
3464 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3465 .deviceId(touchDeviceId)
3466 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3467 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3468 .build());
3469 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3470 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3471
3472 // No more events
3473 leftWindow->assertNoEvents();
3474 rightWindow->assertNoEvents();
3475}
3476
3477/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003478 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3479 * While the touch is down, new hover events from the stylus device should be ignored. After the
3480 * touch is gone, stylus hovering should start working again.
3481 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003482TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003483 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3486 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003487 window->setFrame(Rect(0, 0, 200, 200));
3488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003490
3491 const int32_t stylusDeviceId = 5;
3492 const int32_t touchDeviceId = 4;
3493 // Start hovering with stylus
3494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003495 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003496 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003497 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003498 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003499 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003500 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003501
3502 // Finger down on the window
3503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003504 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003505 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003506 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003507 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003508 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003509 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003510
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003511 // Continue hovering with stylus.
3512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003513 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003514 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3515 AINPUT_SOURCE_STYLUS)
3516 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003517 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003518 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003519 // Hovers continue to work
3520 window->consumeMotionEvent(
3521 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003522
3523 // Lift up the finger
3524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003525 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003526 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3527 AINPUT_SOURCE_TOUCHSCREEN)
3528 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003529 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003530 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003531
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003533 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003534 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3535 AINPUT_SOURCE_STYLUS)
3536 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003538 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003539 window->consumeMotionEvent(
3540 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003541 window->assertNoEvents();
3542}
3543
3544/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003545 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3546 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3547 * check that the stylus hovering continues to work.
3548 */
3549TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3550 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003552 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3553 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003554 window->setFrame(Rect(0, 0, 200, 200));
3555
3556 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3557
3558 const int32_t stylusDeviceId = 5;
3559 const int32_t touchDeviceId = 4;
3560 // Start hovering with stylus
3561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3562 .deviceId(stylusDeviceId)
3563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3564 .build());
3565 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3566
3567 // Finger down on the window
3568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3569 .deviceId(touchDeviceId)
3570 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3571 .build());
3572 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3573
3574 // Continue hovering with stylus.
3575 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3576 .deviceId(stylusDeviceId)
3577 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3578 .build());
3579 // Hovers continue to work
3580 window->consumeMotionEvent(
3581 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3582
3583 // Lift up the finger
3584 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3585 .deviceId(touchDeviceId)
3586 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3587 .build());
3588 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3589
3590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3591 .deviceId(stylusDeviceId)
3592 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3593 .build());
3594 window->consumeMotionEvent(
3595 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3596 window->assertNoEvents();
3597}
3598
3599/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003600 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3601 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3602 *
3603 * Two windows: one on the left and one on the right.
3604 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3605 * Stylus down on the left window, and then touch down on the right window.
3606 * Check that the right window doesn't get touches while the stylus is down on the left window.
3607 */
3608TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3610 sp<FakeWindowHandle> leftWindow =
3611 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003612 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003613 leftWindow->setFrame(Rect(0, 0, 100, 100));
3614
3615 sp<FakeWindowHandle> sbtRightWindow =
3616 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003617 "Stylus blocks touch (right) window",
3618 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003619 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3620 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3621
3622 mDispatcher->onWindowInfosChanged(
3623 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3624
3625 const int32_t stylusDeviceId = 5;
3626 const int32_t touchDeviceId = 4;
3627
3628 // Stylus down in the left window
3629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3630 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3631 .deviceId(stylusDeviceId)
3632 .build());
3633 leftWindow->consumeMotionEvent(
3634 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3635
3636 // Finger tap on the right window
3637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3638 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3639 .deviceId(touchDeviceId)
3640 .build());
3641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3642 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3643 .deviceId(touchDeviceId)
3644 .build());
3645
3646 // The touch should be blocked, because stylus is down somewhere else on screen!
3647 sbtRightWindow->assertNoEvents();
3648
3649 // Continue stylus motion, and ensure it's not impacted.
3650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3651 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3652 .deviceId(stylusDeviceId)
3653 .build());
3654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3655 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3656 .deviceId(stylusDeviceId)
3657 .build());
3658 leftWindow->consumeMotionEvent(
3659 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3660 leftWindow->consumeMotionEvent(
3661 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3662
3663 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3665 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3666 .deviceId(touchDeviceId)
3667 .build());
3668 sbtRightWindow->consumeMotionEvent(
3669 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3670}
3671
3672/**
3673 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3674 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3675 *
3676 * Two windows: one on the left and one on the right.
3677 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3678 * Stylus hover on the left window, and then touch down on the right window.
3679 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3680 */
3681TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3683 sp<FakeWindowHandle> leftWindow =
3684 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003685 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003686 leftWindow->setFrame(Rect(0, 0, 100, 100));
3687
3688 sp<FakeWindowHandle> sbtRightWindow =
3689 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003690 "Stylus blocks touch (right) window",
3691 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003692 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3693 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3694
3695 mDispatcher->onWindowInfosChanged(
3696 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3697
3698 const int32_t stylusDeviceId = 5;
3699 const int32_t touchDeviceId = 4;
3700
3701 // Stylus hover in the left window
3702 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3703 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3704 .deviceId(stylusDeviceId)
3705 .build());
3706 leftWindow->consumeMotionEvent(
3707 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3708
3709 // Finger tap on the right window
3710 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3711 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3712 .deviceId(touchDeviceId)
3713 .build());
3714 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3715 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3716 .deviceId(touchDeviceId)
3717 .build());
3718
3719 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3720 sbtRightWindow->assertNoEvents();
3721
3722 // Continue stylus motion, and ensure it's not impacted.
3723 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3724 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3725 .deviceId(stylusDeviceId)
3726 .build());
3727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3729 .deviceId(stylusDeviceId)
3730 .build());
3731 leftWindow->consumeMotionEvent(
3732 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3733 leftWindow->consumeMotionEvent(
3734 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3735
3736 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3738 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3739 .deviceId(touchDeviceId)
3740 .build());
3741 sbtRightWindow->consumeMotionEvent(
3742 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3743}
3744
3745/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003746 * A spy window above a window with no input channel.
3747 * Start hovering with a stylus device, and then tap with it.
3748 * Ensure spy window receives the entire sequence.
3749 */
3750TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003752 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3753 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003754 spyWindow->setFrame(Rect(0, 0, 200, 200));
3755 spyWindow->setTrustedOverlay(true);
3756 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3758 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003759 window->setNoInputChannel(true);
3760 window->setFrame(Rect(0, 0, 200, 200));
3761
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003762 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003763
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003764 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3766 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3767 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003768 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3769 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003770 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3771 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3772 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003773 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3774
3775 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3777 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3778 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003779 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3780
3781 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003782 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3783 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3784 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003785 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3786
3787 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3789 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3790 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003791 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3792 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3794 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3795 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003796 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3797
3798 // No more events
3799 spyWindow->assertNoEvents();
3800 window->assertNoEvents();
3801}
3802
3803/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003804 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3805 * rejected. But since we already have an ongoing gesture, this event should be processed.
3806 * This prevents inconsistent events being handled inside the dispatcher.
3807 */
3808TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3810
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3812 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003813 window->setFrame(Rect(0, 0, 200, 200));
3814
3815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3816
3817 // Start hovering with stylus
3818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3819 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3820 .build());
3821 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3822
3823 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3825 .build();
3826 // Make this 'hoverExit' event stale
3827 mFakePolicy->setStaleEventTimeout(100ms);
3828 std::this_thread::sleep_for(100ms);
3829
3830 // It shouldn't be dropped by the dispatcher, even though it's stale.
3831 mDispatcher->notifyMotion(hoverExit);
3832 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3833
3834 // Stylus starts hovering again! There should be no crash.
3835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3836 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3837 .build());
3838 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3839}
3840
3841/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003842 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3843 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3844 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3845 * While the mouse is down, new move events from the touch device should be ignored.
3846 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003847TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3848 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003850 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3851 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003852 spyWindow->setFrame(Rect(0, 0, 200, 200));
3853 spyWindow->setTrustedOverlay(true);
3854 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003855 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3856 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003857 window->setFrame(Rect(0, 0, 200, 200));
3858
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003859 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003860
3861 const int32_t mouseDeviceId = 7;
3862 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003863
3864 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3866 .deviceId(mouseDeviceId)
3867 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3868 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003869 spyWindow->consumeMotionEvent(
3870 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3871 window->consumeMotionEvent(
3872 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3873
3874 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3876 .deviceId(touchDeviceId)
3877 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003879 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3880 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3881 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3882 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3883
Prabir Pradhan678438e2023-04-13 19:32:51 +00003884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3885 .deviceId(touchDeviceId)
3886 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3887 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003888 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3889 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3890
3891 // Pilfer the stream
3892 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3893 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3894
Prabir Pradhan678438e2023-04-13 19:32:51 +00003895 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3896 .deviceId(touchDeviceId)
3897 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3898 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003899 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3900
3901 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003902 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3903 .deviceId(mouseDeviceId)
3904 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3906 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003907
3908 spyWindow->consumeMotionEvent(
3909 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3910 spyWindow->consumeMotionEvent(
3911 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3912 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3913
Prabir Pradhan678438e2023-04-13 19:32:51 +00003914 mDispatcher->notifyMotion(
3915 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3916 .deviceId(mouseDeviceId)
3917 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3918 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3919 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3920 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003921 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3922 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3923
3924 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3926 .deviceId(mouseDeviceId)
3927 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3928 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3929 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003930 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3931 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3932
3933 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003934 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3935 .deviceId(touchDeviceId)
3936 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3937 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003938
3939 // No more events
3940 spyWindow->assertNoEvents();
3941 window->assertNoEvents();
3942}
3943
3944/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003945 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3946 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3947 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3948 * While the mouse is down, new move events from the touch device should continue to work.
3949 */
3950TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3951 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3952 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003953 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3954 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003955 spyWindow->setFrame(Rect(0, 0, 200, 200));
3956 spyWindow->setTrustedOverlay(true);
3957 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003958 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3959 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003960 window->setFrame(Rect(0, 0, 200, 200));
3961
3962 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3963
3964 const int32_t mouseDeviceId = 7;
3965 const int32_t touchDeviceId = 4;
3966
3967 // Hover a bit with mouse first
3968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3969 .deviceId(mouseDeviceId)
3970 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3971 .build());
3972 spyWindow->consumeMotionEvent(
3973 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3974 window->consumeMotionEvent(
3975 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3976
3977 // Start touching
3978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3979 .deviceId(touchDeviceId)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3981 .build());
3982
3983 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3984 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3985
3986 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3987 .deviceId(touchDeviceId)
3988 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3989 .build());
3990 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3991 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3992
3993 // Pilfer the stream
3994 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3996 // Hover is not pilfered! Only touch.
3997
3998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3999 .deviceId(touchDeviceId)
4000 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
4001 .build());
4002 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4003
4004 // Mouse down
4005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4006 .deviceId(mouseDeviceId)
4007 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4008 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4009 .build());
4010
4011 spyWindow->consumeMotionEvent(
4012 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4013 spyWindow->consumeMotionEvent(
4014 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4015 window->consumeMotionEvent(
4016 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4017 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4018
4019 mDispatcher->notifyMotion(
4020 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4021 .deviceId(mouseDeviceId)
4022 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4023 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4024 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4025 .build());
4026 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4027 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4028
4029 // Mouse move!
4030 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4031 .deviceId(mouseDeviceId)
4032 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4034 .build());
4035 spyWindow->consumeMotionEvent(
4036 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4037 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4038
4039 // Touch move!
4040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4041 .deviceId(touchDeviceId)
4042 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4043 .build());
4044 spyWindow->consumeMotionEvent(
4045 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4046
4047 // No more events
4048 spyWindow->assertNoEvents();
4049 window->assertNoEvents();
4050}
4051
4052/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004053 * On the display, have a single window, and also an area where there's no window.
4054 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4055 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4056 */
4057TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4059 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004060 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004061
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004062 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004063
4064 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004065 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004066
4067 mDispatcher->waitForIdle();
4068 window->assertNoEvents();
4069
4070 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004071 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004072 mDispatcher->waitForIdle();
4073 window->consumeMotionDown();
4074}
4075
4076/**
4077 * Same test as above, but instead of touching the empty space, the first touch goes to
4078 * non-touchable window.
4079 */
4080TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4082 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004083 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004084 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4085 window1->setTouchable(false);
4086 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004087 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004088 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004090 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004091
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004092 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004093 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004094
4095 mDispatcher->waitForIdle();
4096 window1->assertNoEvents();
4097 window2->assertNoEvents();
4098
4099 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004100 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004101 mDispatcher->waitForIdle();
4102 window2->consumeMotionDown();
4103}
4104
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004105/**
4106 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4107 * to the event time of the first ACTION_DOWN sent to the particular window.
4108 */
4109TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4111 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004112 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004113 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4114 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004115 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004116 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4117
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004118 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004119
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004120 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004121 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004122 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004123
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004124 const std::unique_ptr<MotionEvent> firstDown =
4125 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4126 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004127 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004128
4129 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004130 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004131 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004132
4133 const std::unique_ptr<MotionEvent> secondDown =
4134 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4135 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4136 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4137 // We currently send MOVE events to all windows receiving a split touch when there is any change
4138 // in the touch state, even when none of the pointers in the split window actually moved.
4139 // Document this behavior in the test.
4140 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004141
4142 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004143 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004144 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004145
4146 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4147 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004148
4149 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004150 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004151 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004152
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004153 window2->consumeMotionEvent(
4154 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4155 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004156
4157 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004158 mDispatcher->notifyMotion(
4159 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004160 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004161
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004162 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4163 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4164
4165 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004166 mDispatcher->notifyMotion(
4167 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004168 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004169
4170 window1->consumeMotionEvent(
4171 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4172 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004173}
4174
Garfield Tandf26e862020-07-01 20:18:19 -07004175TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004177 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4178 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004179 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004180 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4181 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004182 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004183
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004184 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004185
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004186 mDispatcher->onWindowInfosChanged(
4187 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004188
4189 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004191 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004192 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4193 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004194 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004195 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004196 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004197
4198 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004200 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004201 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4202 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004203 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004204 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004205 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4206 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004207
4208 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004210 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004211 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4212 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004213 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004214 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004215 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4216 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004217
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004219 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004220 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4221 AINPUT_SOURCE_MOUSE)
4222 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4223 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004224 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004225 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004226 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004227
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004229 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004230 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4231 AINPUT_SOURCE_MOUSE)
4232 .buttonState(0)
4233 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004234 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004235 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004236 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004237
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004239 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004240 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4241 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004243 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004244 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004245
4246 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004248 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004249 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4250 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004251 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004252 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004253 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004254
4255 // No more events
4256 windowLeft->assertNoEvents();
4257 windowRight->assertNoEvents();
4258}
4259
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004260/**
4261 * Put two fingers down (and don't release them) and click the mouse button.
4262 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4263 * currently active gesture should be canceled, and the new one should proceed.
4264 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004265TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4266 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004267 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004268 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4269 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004270 window->setFrame(Rect(0, 0, 600, 800));
4271
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004272 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004273
4274 const int32_t touchDeviceId = 4;
4275 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004276
4277 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4279 .deviceId(touchDeviceId)
4280 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4281 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004282
Prabir Pradhan678438e2023-04-13 19:32:51 +00004283 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4284 .deviceId(touchDeviceId)
4285 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4286 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4287 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004288 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4289 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4290
4291 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004292 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4293 .deviceId(mouseDeviceId)
4294 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4295 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4296 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004297 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4298 WithPointerCount(2u)));
4299 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4300
Prabir Pradhan678438e2023-04-13 19:32:51 +00004301 mDispatcher->notifyMotion(
4302 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4303 .deviceId(mouseDeviceId)
4304 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4305 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4306 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4307 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004308 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4309
4310 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4311 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4313 .deviceId(touchDeviceId)
4314 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4315 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4316 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004317 window->assertNoEvents();
4318}
4319
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004320/**
4321 * Put two fingers down (and don't release them) and click the mouse button.
4322 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4323 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4324 */
4325TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4326 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004328 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4329 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004330 window->setFrame(Rect(0, 0, 600, 800));
4331
4332 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4333
4334 const int32_t touchDeviceId = 4;
4335 const int32_t mouseDeviceId = 6;
4336
4337 // Two pointers down
4338 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4339 .deviceId(touchDeviceId)
4340 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4341 .build());
4342
4343 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4344 .deviceId(touchDeviceId)
4345 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4346 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4347 .build());
4348 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4349 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4350
4351 // Send a series of mouse events for a mouse click
4352 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4353 .deviceId(mouseDeviceId)
4354 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4355 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4356 .build());
4357 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4358
4359 mDispatcher->notifyMotion(
4360 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4361 .deviceId(mouseDeviceId)
4362 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4363 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4364 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4365 .build());
4366 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4367
4368 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4369 // already active gesture, it should be sent normally.
4370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4371 .deviceId(touchDeviceId)
4372 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4373 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4374 .build());
4375 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4376 window->assertNoEvents();
4377}
4378
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004379TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4381
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004382 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4383 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004384 spyWindow->setFrame(Rect(0, 0, 600, 800));
4385 spyWindow->setTrustedOverlay(true);
4386 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004387 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4388 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004389 window->setFrame(Rect(0, 0, 600, 800));
4390
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004391 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004392 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004393
4394 // Send mouse cursor to the window
4395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004396 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004397 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4398 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004399 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004400 .build()));
4401
4402 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4403 WithSource(AINPUT_SOURCE_MOUSE)));
4404 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4405 WithSource(AINPUT_SOURCE_MOUSE)));
4406
4407 window->assertNoEvents();
4408 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004409}
4410
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004411TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4412 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4414
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004415 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4416 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004417 spyWindow->setFrame(Rect(0, 0, 600, 800));
4418 spyWindow->setTrustedOverlay(true);
4419 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004420 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4421 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004422 window->setFrame(Rect(0, 0, 600, 800));
4423
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004424 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004425 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004426
4427 // Send mouse cursor to the window
4428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004429 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004430 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4431 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004432 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004433 .build()));
4434
4435 // Move mouse cursor
4436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004437 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004438 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4439 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004440 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004441 .build()));
4442
4443 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4444 WithSource(AINPUT_SOURCE_MOUSE)));
4445 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4446 WithSource(AINPUT_SOURCE_MOUSE)));
4447 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4448 WithSource(AINPUT_SOURCE_MOUSE)));
4449 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4450 WithSource(AINPUT_SOURCE_MOUSE)));
4451 // Touch down on the window
4452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004453 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004454 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4455 AINPUT_SOURCE_TOUCHSCREEN)
4456 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004457 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004458 .build()));
4459 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4460 WithSource(AINPUT_SOURCE_MOUSE)));
4461 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4462 WithSource(AINPUT_SOURCE_MOUSE)));
4463 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4464 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4465 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4466 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4467
4468 // pilfer the motion, retaining the gesture on the spy window.
4469 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4470 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4471 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4472
4473 // Touch UP on the window
4474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004475 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004476 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4477 AINPUT_SOURCE_TOUCHSCREEN)
4478 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004479 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004480 .build()));
4481 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4482 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4483
4484 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4485 // to send a new gesture. It should again go to both windows (spy and the window below), just
4486 // like the first gesture did, before pilfering. The window configuration has not changed.
4487
4488 // One more tap - DOWN
4489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004490 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004491 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4492 AINPUT_SOURCE_TOUCHSCREEN)
4493 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004494 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004495 .build()));
4496 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4497 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4498 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4499 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4500
4501 // Touch UP on the window
4502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004503 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004504 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4505 AINPUT_SOURCE_TOUCHSCREEN)
4506 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004507 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004508 .build()));
4509 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4510 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4511 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4512 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4513
4514 window->assertNoEvents();
4515 spyWindow->assertNoEvents();
4516}
4517
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004518TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4519 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4521
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004522 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4523 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004524 spyWindow->setFrame(Rect(0, 0, 600, 800));
4525 spyWindow->setTrustedOverlay(true);
4526 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4528 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004529 window->setFrame(Rect(0, 0, 600, 800));
4530
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004531 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004532 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4533
4534 // Send mouse cursor to the window
4535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4536 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4537 .build());
4538
4539 // Move mouse cursor
4540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4541 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4542 .build());
4543
4544 window->consumeMotionEvent(
4545 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4546 spyWindow->consumeMotionEvent(
4547 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4548 window->consumeMotionEvent(
4549 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4550 spyWindow->consumeMotionEvent(
4551 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4552 // Touch down on the window
4553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4554 .deviceId(SECOND_DEVICE_ID)
4555 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4556 .build());
4557 window->consumeMotionEvent(
4558 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4559 spyWindow->consumeMotionEvent(
4560 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4561
4562 // pilfer the motion, retaining the gesture on the spy window.
4563 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4564 window->consumeMotionEvent(
4565 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4566 // Mouse hover is not pilfered
4567
4568 // Touch UP on the window
4569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4570 .deviceId(SECOND_DEVICE_ID)
4571 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4572 .build());
4573 spyWindow->consumeMotionEvent(
4574 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4575
4576 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4577 // to send a new gesture. It should again go to both windows (spy and the window below), just
4578 // like the first gesture did, before pilfering. The window configuration has not changed.
4579
4580 // One more tap - DOWN
4581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4582 .deviceId(SECOND_DEVICE_ID)
4583 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4584 .build());
4585 window->consumeMotionEvent(
4586 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4587 spyWindow->consumeMotionEvent(
4588 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4589
4590 // Touch UP on the window
4591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4592 .deviceId(SECOND_DEVICE_ID)
4593 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4594 .build());
4595 window->consumeMotionEvent(
4596 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4597 spyWindow->consumeMotionEvent(
4598 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4599
4600 // Mouse movement continues normally as well
4601 // Move mouse cursor
4602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4604 .build());
4605 window->consumeMotionEvent(
4606 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4607 spyWindow->consumeMotionEvent(
4608 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4609
4610 window->assertNoEvents();
4611 spyWindow->assertNoEvents();
4612}
4613
Garfield Tandf26e862020-07-01 20:18:19 -07004614// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4615// directly in this test.
4616TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004617 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004618 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4619 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004620 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004621
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004622 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004623
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004624 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004625
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004627 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004628 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4629 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004630 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004631 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004632 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004633 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004635 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004636 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4637 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004638 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004639 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004640 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4641 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004642
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004644 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004645 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4646 AINPUT_SOURCE_MOUSE)
4647 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4648 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004649 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004650 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004651 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004652
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004654 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004655 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4656 AINPUT_SOURCE_MOUSE)
4657 .buttonState(0)
4658 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004659 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004660 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004661 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004662
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004664 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004665 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4666 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004667 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004668 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004669 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004670
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004671 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4672 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4673 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004674 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004675 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4676 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004677 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004678 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004679 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004680}
4681
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004682/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004683 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4684 * is generated.
4685 */
4686TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4689 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004690 window->setFrame(Rect(0, 0, 1200, 800));
4691
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004692 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004693
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004694 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004695
4696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004697 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004698 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4699 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004700 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004701 .build()));
4702 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4703
4704 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004705 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004706 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4707}
4708
4709/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004710 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4711 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004712TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4713 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4714 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004716 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4717 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004718 window->setFrame(Rect(0, 0, 1200, 800));
4719
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004720 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004721
4722 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4723
4724 MotionEventBuilder hoverEnterBuilder =
4725 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4726 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4727 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4729 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4731 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4732 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4733 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4734}
4735
4736/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004737 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4738 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004739TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
4740 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004742 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4743 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004744 window->setFrame(Rect(0, 0, 100, 100));
4745
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004747
4748 const int32_t mouseDeviceId = 7;
4749 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004750
4751 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4753 .deviceId(mouseDeviceId)
4754 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4755 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004756 window->consumeMotionEvent(
4757 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4758
4759 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4761 .deviceId(touchDeviceId)
4762 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4763 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004764
4765 window->consumeMotionEvent(
4766 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4767 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4768}
4769
4770/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004771 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
4772 */
4773TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4774 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004776 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4777 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004778 window->setFrame(Rect(0, 0, 100, 100));
4779
4780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4781
4782 const int32_t mouseDeviceId = 7;
4783 const int32_t touchDeviceId = 4;
4784
4785 // Start hovering with the mouse
4786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4787 .deviceId(mouseDeviceId)
4788 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4789 .build());
4790 window->consumeMotionEvent(
4791 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4792
4793 // Touch goes down
4794 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4795 .deviceId(touchDeviceId)
4796 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4797 .build());
4798 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4799}
4800
4801/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004802 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004803 * The tap causes a HOVER_EXIT event to be generated because the current event
4804 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004805 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004806TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
4807 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004809 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4810 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004811 window->setFrame(Rect(0, 0, 100, 100));
4812
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004813 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4815 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4816 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004817 ASSERT_NO_FATAL_FAILURE(
4818 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4819 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004820
4821 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4823 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4824 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004825 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004826 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4827 WithSource(AINPUT_SOURCE_MOUSE))));
4828
4829 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004830 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4831 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4832
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4834 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4835 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004836 ASSERT_NO_FATAL_FAILURE(
4837 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4838 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4839}
4840
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004841/**
4842 * Send a mouse hover event followed by a tap from touchscreen.
4843 * The tap causes a HOVER_EXIT event to be generated because the current event
4844 * stream's source has been switched.
4845 */
4846TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4847 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004849 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4850 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004851 window->setFrame(Rect(0, 0, 100, 100));
4852
4853 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4855 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4856 .build());
4857
4858 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4859 WithSource(AINPUT_SOURCE_MOUSE)));
4860
4861 // Tap on the window
4862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4863 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4864 .build());
4865
4866 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4867 WithSource(AINPUT_SOURCE_MOUSE)));
4868
4869 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4870 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4871
4872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4873 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4874 .build());
4875
4876 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4877 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4878}
4879
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004880TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4882 sp<FakeWindowHandle> windowDefaultDisplay =
4883 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004884 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004885 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4886 sp<FakeWindowHandle> windowSecondDisplay =
4887 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4888 SECOND_DISPLAY_ID);
4889 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4890
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004891 mDispatcher->onWindowInfosChanged(
4892 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004893
4894 // Set cursor position in window in default display and check that hover enter and move
4895 // events are generated.
4896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004897 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004898 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4899 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004900 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004901 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004902 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004903 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004904
4905 // Remove all windows in secondary display and check that no event happens on window in
4906 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004907 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4908
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004909 windowDefaultDisplay->assertNoEvents();
4910
4911 // Move cursor position in window in default display and check that only hover move
4912 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004913 mDispatcher->onWindowInfosChanged(
4914 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004916 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004917 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4918 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004919 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004920 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004921 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004922 windowDefaultDisplay->consumeMotionEvent(
4923 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4924 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004925 windowDefaultDisplay->assertNoEvents();
4926}
4927
Garfield Tan00f511d2019-06-12 16:55:40 -07004928TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004929 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004930
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004931 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4932 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004933 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004934 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4935 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004936 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004937
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004938 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07004939
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004940 mDispatcher->onWindowInfosChanged(
4941 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004942
4943 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4944 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004946 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004947 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
4948 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004949 windowRight->assertNoEvents();
4950}
4951
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004952TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004954 sp<FakeWindowHandle> window =
4955 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4956 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004957 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004958
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004959 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004960 setFocusedWindow(window);
4961
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004962 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004963
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004964 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004965
4966 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004967 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004968
4969 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4970 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004971 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004972 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004973}
4974
4975TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004976 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004977 sp<FakeWindowHandle> window =
4978 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4979 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004980
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004981 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004982
Prabir Pradhan678438e2023-04-13 19:32:51 +00004983 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004984 AINPUT_SOURCE_TOUCHSCREEN,
4985 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004986
4987 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004988 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004989
4990 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4991 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004992 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004993 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004994 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004995}
4996
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004997TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004999 sp<FakeWindowHandle> window =
5000 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5001 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005002
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005003 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005004
5005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5006 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5007 .build());
5008
5009 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5010
5011 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5012 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5013 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5014
5015 // After the device has been reset, a new hovering stream can be sent to the window
5016 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5017 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5018 .build());
5019 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5020}
5021
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005022TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5023 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005024 sp<FakeWindowHandle> window =
5025 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5026 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005027 window->setFocusable(true);
5028
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005029 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005030 setFocusedWindow(window);
5031
5032 window->consumeFocusEvent(true);
5033
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005034 const NotifyKeyArgs keyArgs =
5035 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005036 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5037 const nsecs_t injectTime = keyArgs.eventTime;
5038 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005039 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005040 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005041 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005042 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5043 std::chrono::nanoseconds(interceptKeyTimeout).count());
5044}
5045
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005046/**
5047 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5048 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005049TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005051 sp<FakeWindowHandle> window =
5052 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5053 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005054 window->setFocusable(true);
5055
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005056 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005057 setFocusedWindow(window);
5058
5059 window->consumeFocusEvent(true);
5060
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005061 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5062 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005063
5064 // Set a value that's significantly larger than the default consumption timeout. If the
5065 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5066 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005067 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005068 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005069 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005070}
5071
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005072/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005073 * Two windows. First is a regular window. Second does not overlap with the first, and has
5074 * WATCH_OUTSIDE_TOUCH.
5075 * Both windows are owned by the same UID.
5076 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5077 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5078 */
5079TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5080 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005081 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5082 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005083 window->setFrame(Rect{0, 0, 100, 100});
5084
5085 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005086 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005087 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005088 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5089 outsideWindow->setWatchOutsideTouch(true);
5090 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005091 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005092
5093 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005094 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005095 AINPUT_SOURCE_TOUCHSCREEN,
5096 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005097 window->consumeMotionDown();
5098 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5099 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5100 outsideWindow->consumeMotionEvent(
5101 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005102
5103 // Ensure outsideWindow doesn't get any more events for the gesture.
5104 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005105 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005106 window->consumeMotionMove();
5107 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005108}
5109
5110/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005111 * Three windows:
5112 * - Left window
5113 * - Right window
5114 * - Outside window(watch for ACTION_OUTSIDE events)
5115 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5116 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5117 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5118 *
5119 * First, device A report a down event landed in the right window, the outside window can receive
5120 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5121 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5122 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5123 * window can receive it, but outside window event can't receive it.
5124 */
5125TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5127 sp<FakeWindowHandle> leftWindow =
5128 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005129 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005130 leftWindow->setFrame(Rect{0, 0, 100, 100});
5131 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5132
5133 sp<FakeWindowHandle> outsideWindow =
5134 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005135 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005136 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5137 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5138 outsideWindow->setWatchOutsideTouch(true);
5139
5140 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5141 std::make_shared<FakeApplicationHandle>();
5142 sp<FakeWindowHandle> rightWindow =
5143 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005144 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005145 rightWindow->setFrame(Rect{100, 0, 200, 100});
5146 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5147
5148 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5149 // when left window or right window is tapped
5150 mDispatcher->onWindowInfosChanged(
5151 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5152 {},
5153 0,
5154 0});
5155
5156 const DeviceId deviceA = 9;
5157 const DeviceId deviceB = 3;
5158
5159 // Tap on right window use device A
5160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5161 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5162 .deviceId(deviceA)
5163 .build());
5164 leftWindow->assertNoEvents();
5165 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5166 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5167 // with zeroed coords.
5168 outsideWindow->consumeMotionEvent(
5169 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5170
5171 // Tap on left window use device B
5172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5173 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5174 .deviceId(deviceB)
5175 .build());
5176 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5177 rightWindow->assertNoEvents();
5178 // Because new gesture down on the left window that has the same owner with outside Window, the
5179 // outside Window should receive the ACTION_OUTSIDE with coords.
5180 outsideWindow->consumeMotionEvent(
5181 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5182
5183 // Ensure that windows that can only accept outside do not receive remaining gestures
5184 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5185 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5186 .deviceId(deviceA)
5187 .build());
5188 leftWindow->assertNoEvents();
5189 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5190
5191 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5192 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5193 .deviceId(deviceB)
5194 .build());
5195 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5196 rightWindow->assertNoEvents();
5197 outsideWindow->assertNoEvents();
5198}
5199
5200/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005201 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5202 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5203 * ACTION_OUTSIDE event is sent per gesture.
5204 */
5205TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5206 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005208 sp<FakeWindowHandle> window =
5209 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5210 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005211 window->setWatchOutsideTouch(true);
5212 window->setFrame(Rect{0, 0, 100, 100});
5213 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005214 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005215 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005216 secondWindow->setFrame(Rect{100, 100, 200, 200});
5217 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005218 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005219 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005220 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005221 mDispatcher->onWindowInfosChanged(
5222 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005223
5224 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005225 mDispatcher->notifyMotion(
5226 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5227 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005228 window->assertNoEvents();
5229 secondWindow->assertNoEvents();
5230
5231 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5232 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005233 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005234 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005235 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005236 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5237 window->consumeMotionEvent(
5238 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005239 secondWindow->consumeMotionDown();
5240 thirdWindow->assertNoEvents();
5241
5242 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5243 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005244 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005245 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5246 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005247 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005248 window->assertNoEvents();
5249 secondWindow->consumeMotionMove();
5250 thirdWindow->consumeMotionDown();
5251}
5252
Prabir Pradhan814fe082022-07-22 20:22:18 +00005253TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5254 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005255 sp<FakeWindowHandle> window =
5256 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5257 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005258 window->setFocusable(true);
5259
Patrick Williamsd828f302023-04-28 17:52:08 -05005260 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005261 setFocusedWindow(window);
5262
5263 window->consumeFocusEvent(true);
5264
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005265 const NotifyKeyArgs keyDown =
5266 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5267 const NotifyKeyArgs keyUp =
5268 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005269 mDispatcher->notifyKey(keyDown);
5270 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005271
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005272 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5273 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005274
5275 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005276 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005277
5278 window->consumeFocusEvent(false);
5279
Prabir Pradhan678438e2023-04-13 19:32:51 +00005280 mDispatcher->notifyKey(keyDown);
5281 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005282 window->assertNoEvents();
5283}
5284
Arthur Hung96483742022-11-15 03:30:48 +00005285TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5286 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005287 sp<FakeWindowHandle> window =
5288 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5289 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005290 // Ensure window is non-split and have some transform.
5291 window->setPreventSplitting(true);
5292 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005293 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005294
5295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005296 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5297 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005298 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005299 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005300
5301 const MotionEvent secondFingerDownEvent =
5302 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005303 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005304 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005305 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5306 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005307 .build();
5308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005309 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005310 InputEventInjectionSync::WAIT_FOR_RESULT))
5311 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5312
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005313 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5314 ASSERT_NE(nullptr, event);
5315 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5316 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5317 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5318 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5319 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005320}
5321
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005322/**
5323 * Two windows: a splittable and a non-splittable.
5324 * The non-splittable window shouldn't receive any "incomplete" gestures.
5325 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5326 * The second pointer should be dropped because the initial window is splittable, so it won't get
5327 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5328 * "incomplete" gestures.
5329 */
5330TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5332 sp<FakeWindowHandle> leftWindow =
5333 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005334 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005335 leftWindow->setPreventSplitting(false);
5336 leftWindow->setFrame(Rect(0, 0, 100, 100));
5337 sp<FakeWindowHandle> rightWindow =
5338 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005339 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005340 rightWindow->setPreventSplitting(true);
5341 rightWindow->setFrame(Rect(100, 100, 200, 200));
5342 mDispatcher->onWindowInfosChanged(
5343 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5344
5345 // Touch down on left, splittable window
5346 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5347 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5348 .build());
5349 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5350
5351 mDispatcher->notifyMotion(
5352 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5353 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5354 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5355 .build());
5356 leftWindow->assertNoEvents();
5357 rightWindow->assertNoEvents();
5358}
5359
Siarhei Vishniakou27fc9f12024-07-13 23:59:47 -07005360/**
5361 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
5362 * down event to the right window. Device B sends a down event to the left window, and then a
5363 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
5364 * POINTER_DOWN event should only go to the left window, and not to the right window.
5365 * This test attempts to reproduce a crash.
5366 */
5367TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
5368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5369 sp<FakeWindowHandle> leftWindow =
5370 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
5371 ui::LogicalDisplayId::DEFAULT);
5372 leftWindow->setFrame(Rect(0, 0, 100, 100));
5373 leftWindow->setPreventSplitting(true);
5374
5375 sp<FakeWindowHandle> rightWindow =
5376 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
5377 ui::LogicalDisplayId::DEFAULT);
5378 rightWindow->setFrame(Rect(100, 0, 200, 100));
5379
5380 mDispatcher->onWindowInfosChanged(
5381 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5382
5383 const DeviceId deviceA = 9;
5384 const DeviceId deviceB = 3;
5385 // Touch the right window with device A
5386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5387 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5388 .deviceId(deviceA)
5389 .build());
5390 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5391 // Touch the left window with device B
5392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5393 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5394 .deviceId(deviceB)
5395 .build());
5396 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5397 // Send a second pointer from device B to the right window. It shouldn't go to the right window
5398 // because the left window prevents splitting.
5399 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5400 .deviceId(deviceB)
5401 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5402 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5403 .build());
5404 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
5405
5406 // Finish the gesture for both devices
5407 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5408 .deviceId(deviceB)
5409 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5410 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5411 .build());
5412 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
5413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5414 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5415 .deviceId(deviceB)
5416 .build());
5417 leftWindow->consumeMotionEvent(
5418 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
5419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5420 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5421 .deviceId(deviceA)
5422 .build());
5423 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
5424}
5425
Harry Cuttsb166c002023-05-09 13:06:05 +00005426TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5429 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005430 window->setFrame(Rect(0, 0, 400, 400));
5431 sp<FakeWindowHandle> trustedOverlay =
5432 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005433 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005434 trustedOverlay->setSpy(true);
5435 trustedOverlay->setTrustedOverlay(true);
5436
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005437 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005438
5439 // Start a three-finger touchpad swipe
5440 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5441 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5442 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5443 .build());
5444 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5445 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5446 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5447 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5448 .build());
5449 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5450 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5451 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5452 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5453 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5454 .build());
5455
5456 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5457 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5458 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5459
5460 // Move the swipe a bit
5461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5462 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5463 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5464 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5465 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5466 .build());
5467
5468 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5469
5470 // End the swipe
5471 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5472 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5473 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5474 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5475 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5476 .build());
5477 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5478 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5479 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5480 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5481 .build());
5482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5483 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5484 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5485 .build());
5486
5487 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5488 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5489 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5490
5491 window->assertNoEvents();
5492}
5493
5494TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005496 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5497 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005498 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005500
5501 // Start a three-finger touchpad swipe
5502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5503 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5504 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5505 .build());
5506 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5507 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5508 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5509 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5510 .build());
5511 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5512 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5513 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5514 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5515 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5516 .build());
5517
5518 // Move the swipe a bit
5519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5520 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5521 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5522 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5523 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5524 .build());
5525
5526 // End the swipe
5527 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5528 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5529 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5530 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5531 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5532 .build());
5533 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5534 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5535 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5536 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5537 .build());
5538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5539 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5540 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5541 .build());
5542
5543 window->assertNoEvents();
5544}
5545
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005546/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005547 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5548 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005549 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005550 */
5551TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005553 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5554 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005555 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005556 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005557
5558 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5559 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5560 .downTime(baseTime + 10)
5561 .eventTime(baseTime + 10)
5562 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5563 .build());
5564
5565 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5566
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005567 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005568 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005569
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005570 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005571
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005572 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5573 .downTime(baseTime + 10)
5574 .eventTime(baseTime + 30)
5575 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5576 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5577 .build());
5578
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005579 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5580
5581 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005582 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5583 .downTime(baseTime + 10)
5584 .eventTime(baseTime + 40)
5585 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5586 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5587 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005588
5589 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5590
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5592 .downTime(baseTime + 10)
5593 .eventTime(baseTime + 50)
5594 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5595 .build());
5596
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005597 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5598
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5600 .downTime(baseTime + 60)
5601 .eventTime(baseTime + 60)
5602 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5603 .build());
5604
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005605 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005606}
5607
5608/**
Hu Guo771a7692023-09-17 20:51:08 +08005609 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5610 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5611 * its coordinates should be converted by the transform of the windows of target screen.
5612 */
5613TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5614 // This case will create a window and a spy window on the default display and mirror
5615 // window on the second display. cancel event is sent through spy window pilferPointers
5616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5617
5618 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005619 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5620 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005621 spyWindowDefaultDisplay->setTrustedOverlay(true);
5622 spyWindowDefaultDisplay->setSpy(true);
5623
5624 sp<FakeWindowHandle> windowDefaultDisplay =
5625 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005626 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005627 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5628
5629 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5630 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5631
5632 // Add the windows to the dispatcher
5633 mDispatcher->onWindowInfosChanged(
5634 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5635 *windowSecondDisplay->getInfo()},
5636 {},
5637 0,
5638 0});
5639
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005640 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005642 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5643 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5645
5646 spyWindowDefaultDisplay->consumeMotionDown();
5647 windowDefaultDisplay->consumeMotionDown();
5648
5649 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5650
5651 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005652 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5653 ASSERT_NE(nullptr, event);
5654 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005655
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005656 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5657 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5658 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5659 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005660 EXPECT_EQ(100, event->getX(0));
5661 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005662}
5663
5664/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005665 * Ensure the correct coordinate spaces are used by InputDispatcher.
5666 *
5667 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5668 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5669 * space.
5670 */
5671class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5672public:
5673 void SetUp() override {
5674 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005675 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005676 }
5677
Linnan Li13bf76a2024-05-05 19:18:02 +08005678 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005679 gui::DisplayInfo info;
5680 info.displayId = displayId;
5681 info.transform = transform;
5682 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005683 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005684 }
5685
5686 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5687 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005688 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005689 }
5690
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005691 void removeAllWindowsAndDisplays() {
5692 mDisplayInfos.clear();
5693 mWindowInfos.clear();
5694 }
5695
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005696 // Set up a test scenario where the display has a scaled projection and there are two windows
5697 // on the display.
5698 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5699 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5700 // respectively.
5701 ui::Transform displayTransform;
5702 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005703 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005704
5705 std::shared_ptr<FakeApplicationHandle> application =
5706 std::make_shared<FakeApplicationHandle>();
5707
5708 // Add two windows to the display. Their frames are represented in the display space.
5709 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005710 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005711 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005712 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5713 addWindow(firstWindow);
5714
5715 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005716 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005717 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005718 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5719 addWindow(secondWindow);
5720 return {std::move(firstWindow), std::move(secondWindow)};
5721 }
5722
5723private:
5724 std::vector<gui::DisplayInfo> mDisplayInfos;
5725 std::vector<gui::WindowInfo> mWindowInfos;
5726};
5727
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005728TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005729 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5730 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005731 // selected so that if the hit test was performed with the point and the bounds being in
5732 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005733 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005734 AINPUT_SOURCE_TOUCHSCREEN,
5735 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005736
5737 firstWindow->consumeMotionDown();
5738 secondWindow->assertNoEvents();
5739}
5740
5741// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5742// the event should be treated as being in the logical display space.
5743TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5744 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5745 // Send down to the first window. The point is represented in the logical display space. The
5746 // point is selected so that if the hit test was done in logical display space, then it would
5747 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005748 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005749 PointF{75 * 2, 55 * 4});
5750
5751 firstWindow->consumeMotionDown();
5752 secondWindow->assertNoEvents();
5753}
5754
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005755// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5756// event should be treated as being in the logical display space.
5757TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5758 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5759
5760 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5761 ui::Transform injectedEventTransform;
5762 injectedEventTransform.set(matrix);
5763 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5764 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5765
5766 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005767 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005768 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005769 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005770 .x(untransformedPoint.x)
5771 .y(untransformedPoint.y))
5772 .build();
5773 event.transform(matrix);
5774
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005775 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005776 InputEventInjectionSync::WAIT_FOR_RESULT);
5777
5778 firstWindow->consumeMotionDown();
5779 secondWindow->assertNoEvents();
5780}
5781
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005782TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5783 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5784
5785 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005786 mDispatcher->notifyMotion(
5787 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5788 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005789
5790 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005791 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5792 ASSERT_NE(nullptr, event);
5793 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005794
5795 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005796 EXPECT_EQ(300, event->getRawX(0));
5797 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005798
5799 // Ensure that the x and y values are in the window's coordinate space.
5800 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5801 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005802 EXPECT_EQ(100, event->getX(0));
5803 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005804}
5805
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005806TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5807 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5808 // The monitor will always receive events in the logical display's coordinate space, because
5809 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005810 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005811
5812 // Send down to the first window.
5813 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005814 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005815 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5816 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5817
5818 // Second pointer goes down on second window.
5819 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005820 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005821 {PointF{50, 100}, PointF{150, 220}}));
5822 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5823 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5824 {1, PointF{300, 880}}};
5825 monitor.consumeMotionEvent(
5826 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5827
5828 mDispatcher->cancelCurrentTouch();
5829
5830 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5831 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5832 monitor.consumeMotionEvent(
5833 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5834}
5835
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005836TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5837 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5838
5839 // Send down to the first window.
5840 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005841 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005842 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5843
5844 // The pointer is transferred to the second window, and the second window receives it in the
5845 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005846 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005847 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5848 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5849}
5850
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005851TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5852 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5853
5854 // Send hover move to the second window, and ensure it shows up as hover enter.
5855 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005856 ui::LogicalDisplayId::DEFAULT,
5857 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005858 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5859 WithCoords(100, 80), WithRawCoords(300, 880)));
5860
5861 // Touch down at the same location and ensure a hover exit is synthesized.
5862 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005863 ui::LogicalDisplayId::DEFAULT,
5864 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005865 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5866 WithRawCoords(300, 880)));
5867 secondWindow->consumeMotionEvent(
5868 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5869 secondWindow->assertNoEvents();
5870 firstWindow->assertNoEvents();
5871}
5872
Prabir Pradhan453ae732023-10-13 14:30:14 +00005873// Same as above, but while the window is being mirrored.
5874TEST_F(InputDispatcherDisplayProjectionTest,
5875 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5876 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5877
5878 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5879 ui::Transform secondDisplayTransform;
5880 secondDisplayTransform.set(matrix);
5881 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5882
5883 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5884 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5885 addWindow(secondWindowClone);
5886
5887 // Send hover move to the second window, and ensure it shows up as hover enter.
5888 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005889 ui::LogicalDisplayId::DEFAULT,
5890 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005891 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5892 WithCoords(100, 80), WithRawCoords(300, 880)));
5893
5894 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5895 // display.
5896 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005897 ui::LogicalDisplayId::DEFAULT,
5898 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005899 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5900 WithRawCoords(300, 880)));
5901 secondWindow->consumeMotionEvent(
5902 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5903 secondWindow->assertNoEvents();
5904 firstWindow->assertNoEvents();
5905}
5906
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005907TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5908 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5909
5910 // Send hover enter to second window
5911 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005912 ui::LogicalDisplayId::DEFAULT,
5913 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005914 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5915 WithCoords(100, 80), WithRawCoords(300, 880)));
5916
5917 mDispatcher->cancelCurrentTouch();
5918
5919 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5920 WithRawCoords(300, 880)));
5921 secondWindow->assertNoEvents();
5922 firstWindow->assertNoEvents();
5923}
5924
Prabir Pradhan453ae732023-10-13 14:30:14 +00005925// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005926TEST_F(InputDispatcherDisplayProjectionTest,
5927 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5928 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5929
5930 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5931 ui::Transform secondDisplayTransform;
5932 secondDisplayTransform.set(matrix);
5933 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5934
5935 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5936 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5937 addWindow(secondWindowClone);
5938
5939 // Send hover enter to second window
5940 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005941 ui::LogicalDisplayId::DEFAULT,
5942 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00005943 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5944 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005945 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005946
5947 mDispatcher->cancelCurrentTouch();
5948
5949 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5950 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5951 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005952 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005953 secondWindow->assertNoEvents();
5954 firstWindow->assertNoEvents();
5955}
5956
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005957/** Ensure consistent behavior of InputDispatcher in all orientations. */
5958class InputDispatcherDisplayOrientationFixture
5959 : public InputDispatcherDisplayProjectionTest,
5960 public ::testing::WithParamInterface<ui::Rotation> {};
5961
5962// This test verifies the touchable region of a window for all rotations of the display by tapping
5963// in different locations on the display, specifically points close to the four corners of a
5964// window.
5965TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5966 constexpr static int32_t displayWidth = 400;
5967 constexpr static int32_t displayHeight = 800;
5968
5969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5970
5971 const auto rotation = GetParam();
5972
5973 // Set up the display with the specified rotation.
5974 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5975 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5976 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5977 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5978 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005979 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005980
5981 // Create a window with its bounds determined in the logical display.
5982 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5983 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005984 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5985 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005986 window->setFrame(frameInDisplay, displayTransform);
5987 addWindow(window);
5988
5989 // The following points in logical display space should be inside the window.
5990 static const std::array<vec2, 4> insidePoints{
5991 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5992 for (const auto pointInsideWindow : insidePoints) {
5993 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5994 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005995 mDispatcher->notifyMotion(
5996 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5997 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005998 window->consumeMotionDown();
5999
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006000 mDispatcher->notifyMotion(
6001 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6002 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006003 window->consumeMotionUp();
6004 }
6005
6006 // The following points in logical display space should be outside the window.
6007 static const std::array<vec2, 5> outsidePoints{
6008 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6009 for (const auto pointOutsideWindow : outsidePoints) {
6010 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6011 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006012 mDispatcher->notifyMotion(
6013 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6014 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006015
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006016 mDispatcher->notifyMotion(
6017 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6018 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006019 }
6020 window->assertNoEvents();
6021}
6022
Linnan Li5e5645e2024-03-05 14:43:05 +00006023// This test verifies the occlusion detection for all rotations of the display by tapping
6024// in different locations on the display, specifically points close to the four corners of a
6025// window.
6026TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6027 constexpr static int32_t displayWidth = 400;
6028 constexpr static int32_t displayHeight = 800;
6029
6030 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6031 std::make_shared<FakeApplicationHandle>();
6032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6033
6034 const auto rotation = GetParam();
6035
6036 // Set up the display with the specified rotation.
6037 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6038 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6039 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6040 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6041 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006042 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006043
6044 // Create a window that not trusted.
6045 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6046
6047 const Rect untrustedWindowFrameInDisplay =
6048 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6049
6050 sp<FakeWindowHandle> untrustedWindow =
6051 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006052 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006053 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6054 untrustedWindow->setTrustedOverlay(false);
6055 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6056 untrustedWindow->setTouchable(false);
6057 untrustedWindow->setAlpha(1.0f);
6058 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6059 addWindow(untrustedWindow);
6060
6061 // Create a simple app window below the untrusted window.
6062 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6063 const Rect simpleAppWindowFrameInDisplay =
6064 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6065
6066 sp<FakeWindowHandle> simpleAppWindow =
6067 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006068 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006069 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6070 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6071 addWindow(simpleAppWindow);
6072
6073 // The following points in logical display space should be inside the untrusted window, so
6074 // the simple window could not receive events that coordinate is these point.
6075 static const std::array<vec2, 4> untrustedPoints{
6076 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6077
6078 for (const auto untrustedPoint : untrustedPoints) {
6079 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6080 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006081 mDispatcher->notifyMotion(
6082 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6083 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6084 mDispatcher->notifyMotion(
6085 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6086 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006087 }
6088 untrustedWindow->assertNoEvents();
6089 simpleAppWindow->assertNoEvents();
6090 // The following points in logical display space should be outside the untrusted window, so
6091 // the simple window should receive events that coordinate is these point.
6092 static const std::array<vec2, 5> trustedPoints{
6093 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6094 for (const auto trustedPoint : trustedPoints) {
6095 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6096 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006097 mDispatcher->notifyMotion(
6098 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6099 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6100 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006101 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006102 mDispatcher->notifyMotion(
6103 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6104 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6105 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006106 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6107 }
6108 untrustedWindow->assertNoEvents();
6109}
6110
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006111// Run the precision tests for all rotations.
6112INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6113 InputDispatcherDisplayOrientationFixture,
6114 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6115 ui::ROTATION_270),
6116 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6117 return ftl::enum_string(testParamInfo.param);
6118 });
6119
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006120using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6121 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006122
6123class TransferTouchFixture : public InputDispatcherTest,
6124 public ::testing::WithParamInterface<TransferFunction> {};
6125
6126TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006128
6129 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006130 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006131 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006132 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006133 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006134 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006135 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006136 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006137 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006138 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6139 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006140 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006141 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged(
6143 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006144 setFocusedWindow(firstWindow);
6145 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006146
6147 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006148 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006149 AINPUT_SOURCE_TOUCHSCREEN,
6150 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006151
Svet Ganov5d3bc372020-01-26 23:11:07 -08006152 // Only the first window should get the down event
6153 firstWindow->consumeMotionDown();
6154 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006155 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006156 // Dispatcher reports pointer down outside focus for the wallpaper
6157 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006158
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006159 // Transfer touch to the second window
6160 TransferFunction f = GetParam();
6161 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6162 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006163 // The first window gets cancel and the second gets down
6164 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006165 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6166 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6167 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006168 // There should not be any changes to the focused window when transferring touch
6169 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006170
6171 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006172 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006173 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006174 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006175 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006176 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6177 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006178 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006179}
6180
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006181/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006182 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6183 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6184 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006185 * natural to the user.
6186 * In this test, we are sending a pointer to both spy window and first window. We then try to
6187 * transfer touch to the second window. The dispatcher should identify the first window as the
6188 * one that should lose the gesture, and therefore the action should be to move the gesture from
6189 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006190 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6191 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006192 */
6193TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6195
6196 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006197 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6198 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006199 spyWindow->setTrustedOverlay(true);
6200 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006201 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6202 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006203 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006204 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6205 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006206
6207 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006208 mDispatcher->onWindowInfosChanged(
6209 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006210
6211 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006212 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006213 AINPUT_SOURCE_TOUCHSCREEN,
6214 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006215 // Only the first window and spy should get the down event
6216 spyWindow->consumeMotionDown();
6217 firstWindow->consumeMotionDown();
6218
6219 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006220 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006221 TransferFunction f = GetParam();
6222 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6223 ASSERT_TRUE(success);
6224 // The first window gets cancel and the second gets down
6225 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006226 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6227 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006228
6229 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006230 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006231 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006232 // The first window gets no events and the second+spy get up
6233 firstWindow->assertNoEvents();
6234 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006235 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6236 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006237}
6238
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006239TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006240 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006241
6242 PointF touchPoint = {10, 10};
6243
6244 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006245 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006246 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006247 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006248 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006249 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006250 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006251 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006252 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006253
6254 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006255 mDispatcher->onWindowInfosChanged(
6256 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006257
6258 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006259 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006260 AINPUT_SOURCE_TOUCHSCREEN,
6261 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006262 // Only the first window should get the down event
6263 firstWindow->consumeMotionDown();
6264 secondWindow->assertNoEvents();
6265
6266 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006267 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006268 ui::LogicalDisplayId::DEFAULT,
6269 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006270 // Only the first window should get the pointer down event
6271 firstWindow->consumeMotionPointerDown(1);
6272 secondWindow->assertNoEvents();
6273
6274 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006275 TransferFunction f = GetParam();
6276 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6277 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006278 // The first window gets cancel and the second gets down and pointer down
6279 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006280 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6281 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6282 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006283 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006284
6285 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006286 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006287 ui::LogicalDisplayId::DEFAULT,
6288 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006289 // The first window gets nothing and the second gets pointer up
6290 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006291 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6292 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6293 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6294 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006295
6296 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006297 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006298 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006299 // The first window gets nothing and the second gets up
6300 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006301 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6302 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006303}
6304
Arthur Hungc539dbb2022-12-08 07:45:36 +00006305TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6307
6308 // Create a couple of windows
6309 sp<FakeWindowHandle> firstWindow =
6310 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006311 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006312 firstWindow->setDupTouchToWallpaper(true);
6313 sp<FakeWindowHandle> secondWindow =
6314 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006315 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006316 secondWindow->setDupTouchToWallpaper(true);
6317
6318 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006319 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6320 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006321 wallpaper1->setIsWallpaper(true);
6322
6323 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006324 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6325 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006326 wallpaper2->setIsWallpaper(true);
6327 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006328 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6329 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6330 {},
6331 0,
6332 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006333
6334 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006335 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006336 AINPUT_SOURCE_TOUCHSCREEN,
6337 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006338
6339 // Only the first window should get the down event
6340 firstWindow->consumeMotionDown();
6341 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006342 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006343 wallpaper2->assertNoEvents();
6344
6345 // Transfer touch focus to the second window
6346 TransferFunction f = GetParam();
6347 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6348 ASSERT_TRUE(success);
6349
6350 // The first window gets cancel and the second gets down
6351 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006352 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6353 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6354 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6355 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006356 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006357
6358 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006359 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006360 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006361 // The first window gets no events and the second gets up
6362 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006363 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6364 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006365 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006366 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006367 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006368}
6369
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006370// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006371// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006372// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006373INSTANTIATE_TEST_SUITE_P(
6374 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6375 ::testing::Values(
6376 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6377 sp<IBinder> destChannelToken) {
6378 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006379 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006380 },
6381 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6382 sp<IBinder> to) {
6383 return dispatcher->transferTouchGesture(from, to,
6384 /*isDragAndDrop=*/false);
6385 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006386
Prabir Pradhan367f3432024-02-13 23:05:58 +00006387TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006389
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006390 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006391 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006392 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006393 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006394
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006395 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006396 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006397 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006398 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006399
6400 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006401 mDispatcher->onWindowInfosChanged(
6402 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006403
6404 PointF pointInFirst = {300, 200};
6405 PointF pointInSecond = {300, 600};
6406
6407 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006409 AINPUT_SOURCE_TOUCHSCREEN,
6410 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006411 // Only the first window should get the down event
6412 firstWindow->consumeMotionDown();
6413 secondWindow->assertNoEvents();
6414
6415 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006416 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006417 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006418 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006419 // The first window gets a move and the second a down
6420 firstWindow->consumeMotionMove();
6421 secondWindow->consumeMotionDown();
6422
Prabir Pradhan367f3432024-02-13 23:05:58 +00006423 // Transfer touch to the second window
6424 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006425 // The first window gets cancel and the new gets pointer down (it already saw down)
6426 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006427 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006428 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006429
6430 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006431 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006432 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006433 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006434 // The first window gets nothing and the second gets pointer up
6435 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006436 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6437 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6438 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6439 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006440
6441 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006442 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006443 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006444 // The first window gets nothing and the second gets up
6445 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006446 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6447 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006448}
6449
Prabir Pradhan367f3432024-02-13 23:05:58 +00006450// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6451// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6452// receiving touch is not supported, so the touch should continue on those windows and the
6453// transferred-to window should get nothing.
6454TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6456
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006457 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006458 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006459 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006460 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006461
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006462 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006463 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006464 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006465 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006466
6467 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006468 mDispatcher->onWindowInfosChanged(
6469 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006470
6471 PointF pointInFirst = {300, 200};
6472 PointF pointInSecond = {300, 600};
6473
6474 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006475 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006476 AINPUT_SOURCE_TOUCHSCREEN,
6477 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006478 // Only the first window should get the down event
6479 firstWindow->consumeMotionDown();
6480 secondWindow->assertNoEvents();
6481
6482 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006483 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006484 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006485 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006486 // The first window gets a move and the second a down
6487 firstWindow->consumeMotionMove();
6488 secondWindow->consumeMotionDown();
6489
6490 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006491 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6492 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006493 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006494 ASSERT_FALSE(transferred);
6495 firstWindow->assertNoEvents();
6496 secondWindow->assertNoEvents();
6497
6498 // The rest of the dispatch should proceed as normal
6499 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006500 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006501 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006502 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006503 // The first window gets MOVE and the second gets pointer up
6504 firstWindow->consumeMotionMove();
6505 secondWindow->consumeMotionUp();
6506
6507 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006508 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006509 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006510 // The first window gets nothing and the second gets up
6511 firstWindow->consumeMotionUp();
6512 secondWindow->assertNoEvents();
6513}
6514
Arthur Hungabbb9d82021-09-01 14:52:30 +00006515// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006516// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006517// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006518TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006519 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6520 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006521 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6522 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006523 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006524 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006525 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6526 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006527 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006528
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006529 sp<FakeWindowHandle> mirrorWindowInPrimary =
6530 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006531 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006532
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006533 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006534 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006535
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006536 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006537 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006538
6539 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006540 mDispatcher->onWindowInfosChanged(
6541 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6542 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6543 *secondWindowInPrimary->getInfo()},
6544 {},
6545 0,
6546 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006547
6548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006549 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6550 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6552
6553 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006554 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006555
Prabir Pradhan367f3432024-02-13 23:05:58 +00006556 // Transfer touch
6557 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6558 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006559 // The first window gets cancel.
6560 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006561 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006562 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006563
6564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006565 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006566 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6568 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006569 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006570 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006571
6572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006573 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006574 {150, 50}))
6575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6576 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006577 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6578 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006579}
6580
Prabir Pradhan367f3432024-02-13 23:05:58 +00006581// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6582// 'transferTouchOnDisplay' api.
6583TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6585 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006586 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6587 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006588 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006589 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006590 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6591 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006592 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006593
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006594 sp<FakeWindowHandle> mirrorWindowInPrimary =
6595 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006596 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006597
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006598 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006599 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006600
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006601 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006602 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006603
6604 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006605 mDispatcher->onWindowInfosChanged(
6606 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6607 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6608 *secondWindowInPrimary->getInfo()},
6609 {},
6610 0,
6611 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006612
6613 // Touch on second display.
6614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006615 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6616 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6618
6619 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006620 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006621
6622 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006623 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6624 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006625
6626 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006627 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006628 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6629 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006630
6631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006632 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006633 SECOND_DISPLAY_ID, {150, 50}))
6634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006635 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006636 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6637 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006638
6639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006640 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006642 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006643 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006644}
6645
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006646TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006648 sp<FakeWindowHandle> window =
6649 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6650 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006651
Vishnu Nair47074b82020-08-14 11:54:47 -07006652 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006653 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006654 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006655
6656 window->consumeFocusEvent(true);
6657
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006658 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006659
6660 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006661 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006662
6663 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006664 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006665 mFakePolicy->assertUserActivityPoked();
6666}
6667
6668TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006670 sp<FakeWindowHandle> window =
6671 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6672 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006673
6674 window->setDisableUserActivity(true);
6675 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006676 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006677 setFocusedWindow(window);
6678
6679 window->consumeFocusEvent(true);
6680
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006681 mDispatcher->notifyKey(
6682 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006683
6684 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006685 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006686
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006687 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006688 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006689 mFakePolicy->assertUserActivityNotPoked();
6690}
6691
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006692TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00006693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006694 sp<FakeWindowHandle> window =
6695 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6696 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006697
6698 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006699 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006700 setFocusedWindow(window);
6701
6702 window->consumeFocusEvent(true);
6703
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006704 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6705
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006706 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006707 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006708 mDispatcher->waitForIdle();
6709
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006710 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00006711 window->assertNoEvents();
6712
6713 // Should have poked user activity
6714 mFakePolicy->assertUserActivityPoked();
6715}
6716
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006717TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00006718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006719 sp<FakeWindowHandle> window =
6720 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6721 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006722
6723 window->setDisableUserActivity(true);
6724 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006726 setFocusedWindow(window);
6727
6728 window->consumeFocusEvent(true);
6729
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006730 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6731
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006732 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006733 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006734 mDispatcher->waitForIdle();
6735
6736 // System key is not passed down
6737 window->assertNoEvents();
6738
6739 // Should have poked user activity
6740 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006741}
6742
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006743class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
6744 public ::testing::WithParamInterface<bool> {};
6745
6746TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
6747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6748 sp<FakeWindowHandle> window =
6749 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6750 ui::LogicalDisplayId::DEFAULT);
6751
6752 window->setDisableUserActivity(GetParam());
6753
6754 window->setFocusable(true);
6755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6756 setFocusedWindow(window);
6757
6758 window->consumeFocusEvent(true);
6759
6760 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
6761 .keyCode(AKEYCODE_A)
6762 .policyFlags(0)
6763 .build());
6764 mDispatcher->waitForIdle();
6765
6766 // Key is not passed down
6767 window->assertNoEvents();
6768
6769 // Should not have poked user activity
6770 mFakePolicy->assertUserActivityNotPoked();
6771}
6772
6773INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
6774 ::testing::Bool());
6775
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006776TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006778 sp<FakeWindowHandle> window =
6779 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6780 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006781
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006782 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006783
6784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006785 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006786 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6788
6789 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006790 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006791
6792 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006793 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006794 mFakePolicy->assertUserActivityPoked();
6795}
6796
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006797TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006799 sp<FakeWindowHandle> window =
6800 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6801 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006802
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006803 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006804
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006805 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006806 mDispatcher->waitForIdle();
6807
6808 window->assertNoEvents();
6809}
6810
6811// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6812TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006814 sp<FakeWindowHandle> window =
6815 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6816 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006817
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006818 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006819
6820 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006821 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006822 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006823 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006824 AINPUT_SOURCE_TOUCHSCREEN,
6825 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006826
6827 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006828 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006829 window->assertNoEvents(); // Key event or focus event will not be received
6830}
6831
arthurhungea3f4fc2020-12-21 23:18:53 +08006832TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6834
arthurhungea3f4fc2020-12-21 23:18:53 +08006835 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006836 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006837 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006838 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006839
arthurhungea3f4fc2020-12-21 23:18:53 +08006840 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006841 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006842 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006843 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006844
6845 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006846 mDispatcher->onWindowInfosChanged(
6847 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006848
6849 PointF pointInFirst = {300, 200};
6850 PointF pointInSecond = {300, 600};
6851
6852 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006853 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006854 AINPUT_SOURCE_TOUCHSCREEN,
6855 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006856 // Only the first window should get the down event
6857 firstWindow->consumeMotionDown();
6858 secondWindow->assertNoEvents();
6859
6860 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006861 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006862 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006863 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006864 // The first window gets a move and the second a down
6865 firstWindow->consumeMotionMove();
6866 secondWindow->consumeMotionDown();
6867
6868 // Send pointer cancel to the second window
6869 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006870 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
6871 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08006872 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006873 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006874 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006875 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6876 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08006877
6878 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006879 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006880 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006881 // The first window gets up and the second gets nothing.
6882 firstWindow->consumeMotionUp();
6883 secondWindow->assertNoEvents();
6884}
6885
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006886TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6888
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006889 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6890 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006891 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006892 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6893 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6894 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6895
Harry Cutts33476232023-01-30 19:57:29 +00006896 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006897 window->assertNoEvents();
6898 mDispatcher->waitForIdle();
6899}
6900
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006901using InputDispatcherMonitorTest = InputDispatcherTest;
6902
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006903/**
6904 * Two entities that receive touch: A window, and a global monitor.
6905 * The touch goes to the window, and then the window disappears.
6906 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6907 * for the monitor, as well.
6908 * 1. foregroundWindow
6909 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6910 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006911TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006913 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
6914 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006915
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006916 FakeMonitorReceiver monitor =
6917 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006918
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006919 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006921 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6922 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6924
6925 // Both the foreground window and the global monitor should receive the touch down
6926 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006927 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006928
6929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006930 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006931 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006932 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6933
6934 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006935 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006936
6937 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006938 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006939 window->consumeMotionCancel();
6940 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6941
6942 // If more events come in, there will be no more foreground window to send them to. This will
6943 // cause a cancel for the monitor, as well.
6944 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006945 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006946 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006947 << "Injection should fail because the window was removed";
6948 window->assertNoEvents();
6949 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006950 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006951}
6952
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006953TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006955 sp<FakeWindowHandle> window =
6956 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6957 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006958 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006959
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006960 FakeMonitorReceiver monitor =
6961 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006962
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006964 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6965 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006967 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
6968 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006969}
6970
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006971TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006972 FakeMonitorReceiver monitor =
6973 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006974
Chris Yea209fde2020-07-22 13:54:51 -07006975 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006976 sp<FakeWindowHandle> window =
6977 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6978 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006979 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006980
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006982 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6983 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006985 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
6986 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006987
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006988 // Pilfer pointers from the monitor.
6989 // This should not do anything and the window should continue to receive events.
6990 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006991
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006993 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006994 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006996
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006997 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
6998 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006999}
7000
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007001TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007003 sp<FakeWindowHandle> window =
7004 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7005 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007006 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007007 window->setWindowOffset(20, 40);
7008 window->setWindowTransform(0, 1, -1, 0);
7009
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007010 FakeMonitorReceiver monitor =
7011 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007012
7013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007014 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7015 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007017 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007018 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7019 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007020 // Even though window has transform, gesture monitor must not.
7021 ASSERT_EQ(ui::Transform(), event->getTransform());
7022}
7023
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007024TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007026 FakeMonitorReceiver monitor =
7027 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007028
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007029 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007030 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7031 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007032 << "Injection should fail if there is a monitor, but no touchable window";
7033 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007034}
7035
Linnan Lid8150952024-01-26 18:07:17 +00007036/**
7037 * Two displays
7038 * The first monitor has a foreground window, a monitor
7039 * The second window has only one monitor.
7040 * We first inject a Down event into the first display, this injection should succeed and both
7041 * the foreground window and monitor should receive a down event, then inject a Down event into
7042 * the second display as well, this injection should fail, at this point, the first display
7043 * window and monitor should not receive a cancel or any other event.
7044 * Continue to inject Move and UP events to the first display, the events should be received
7045 * normally by the foreground window and monitor.
7046 */
7047TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007049 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7050 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007051
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007052 FakeMonitorReceiver monitor =
7053 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007054 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7055
7056 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007058 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7059 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007060 << "The down event injected into the first display should succeed";
7061
7062 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007063 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007064
7065 ASSERT_EQ(InputEventInjectionResult::FAILED,
7066 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7067 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007068 << "The down event injected into the second display should fail since there's no "
7069 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007070
7071 // Continue to inject event to first display.
7072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7073 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007074 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007075 << "The move event injected into the first display should succeed";
7076
7077 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007078 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007079
7080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007081 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007082 {110, 220}))
7083 << "The up event injected into the first display should succeed";
7084
7085 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007086 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007087
7088 window->assertNoEvents();
7089 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007090 secondMonitor.assertNoEvents();
7091}
7092
7093/**
7094 * Two displays
7095 * There is a monitor and foreground window on each display.
7096 * First, we inject down events into each of the two displays, at this point, the foreground windows
7097 * and monitors on both displays should receive down events.
7098 * At this point, the foreground window of the second display goes away, the gone window should
7099 * receive the cancel event, and the other windows and monitors should not receive any events.
7100 * Inject a move event into the second display. At this point, the injection should fail because
7101 * the second display no longer has a foreground window. At this point, the monitor on the second
7102 * display should receive a cancel event, and any windows or monitors on the first display should
7103 * not receive any events, and any subsequent injection of events into the second display should
7104 * also fail.
7105 * Continue to inject events into the first display, and the events should all be injected
7106 * successfully and received normally.
7107 */
7108TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007110 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7111 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007112 sp<FakeWindowHandle> secondWindow =
7113 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7114 SECOND_DISPLAY_ID);
7115
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007116 FakeMonitorReceiver monitor =
7117 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007118 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7119
7120 // There is a foreground window on both displays.
7121 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007123 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7124 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007125 << "The down event injected into the first display should succeed";
7126
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007127 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7128 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007129
7130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7131 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7132 {100, 200}))
7133 << "The down event injected into the second display should succeed";
7134
Linnan Lid8150952024-01-26 18:07:17 +00007135 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7136 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7137
7138 // Now second window is gone away.
7139 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7140
7141 // The gone window should receive a cancel, and the monitor on the second display should not
7142 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007143 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7144 secondMonitor.assertNoEvents();
7145
7146 ASSERT_EQ(InputEventInjectionResult::FAILED,
7147 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7148 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007149 << "The move event injected into the second display should fail because there's no "
7150 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007151 // Now the monitor on the second display should receive a cancel event.
7152 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007153
7154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7155 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007156 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007157 << "The move event injected into the first display should succeed";
7158
7159 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007160 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007161
7162 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007163 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7164 {110, 220}))
7165 << "The up event injected into the second display should fail because there's no "
7166 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007167
7168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007169 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007170 {110, 220}))
7171 << "The up event injected into the first display should succeed";
7172
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007173 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7174 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007175
Linnan Lid8150952024-01-26 18:07:17 +00007176 window->assertNoEvents();
7177 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007178 secondWindow->assertNoEvents();
7179 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007180}
7181
7182/**
7183 * One display with transform
7184 * There is a foreground window and a monitor on the display
7185 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7186 * event and move event, then let the foreground window go away, the foreground window receives
7187 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7188 * by the monitor should be with the same transform as the display
7189 */
7190TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007192 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7193 ui::LogicalDisplayId::DEFAULT);
7194 FakeMonitorReceiver monitor =
7195 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007196
7197 ui::Transform transform;
7198 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7199
7200 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007201 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007202 displayInfo.transform = transform;
7203
7204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7205
7206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007207 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7208 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007209 << "The down event injected should succeed";
7210
7211 window->consumeMotionDown();
7212 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7213 EXPECT_EQ(transform, downMotionEvent->getTransform());
7214 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7215
7216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7217 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007218 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007219 << "The move event injected should succeed";
7220
7221 window->consumeMotionMove();
7222 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7223 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7224 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7225
7226 // Let foreground window gone
7227 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7228
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007229 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007230 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007231
7232 ASSERT_EQ(InputEventInjectionResult::FAILED,
7233 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007234 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007235 << "The move event injected should failed";
7236 // Now foreground should not receive any events, but monitor should receive a cancel event
7237 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007238 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7239 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007240 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007241 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7242
7243 // Other event inject to this display should fail.
7244 ASSERT_EQ(InputEventInjectionResult::FAILED,
7245 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007246 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007247 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007248 window->assertNoEvents();
7249 monitor.assertNoEvents();
7250}
7251
chaviw81e2bb92019-12-18 15:03:51 -08007252TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007253 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007254 sp<FakeWindowHandle> window =
7255 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7256 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007257
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007259
7260 NotifyMotionArgs motionArgs =
7261 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007262 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007263
Prabir Pradhan678438e2023-04-13 19:32:51 +00007264 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007265 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007266 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007267
7268 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007269 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007270 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7271 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7272 motionArgs.pointerCoords[0].getX() - 10);
7273
Prabir Pradhan678438e2023-04-13 19:32:51 +00007274 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007275 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007276}
7277
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007278/**
7279 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7280 * the device default right away. In the test scenario, we check both the default value,
7281 * and the action of enabling / disabling.
7282 */
7283TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007285 sp<FakeWindowHandle> window =
7286 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7287 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007288 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007289
7290 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007291 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007292 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007293
7294 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007295 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007296 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007297 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007298
7299 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007300 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007301 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007302 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007303
7304 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007305 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007306 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007307 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007308 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007309 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007310 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007311 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007312
7313 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007314 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007315 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007316 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007317
7318 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007319 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007320 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007321 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007322 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007323 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007324 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007325 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007326
7327 window->assertNoEvents();
7328}
7329
Gang Wange9087892020-01-07 12:17:14 -05007330TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007332 sp<FakeWindowHandle> window =
7333 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7334 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007335
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007336 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007337 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007338
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007339 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007340 setFocusedWindow(window);
7341
Harry Cutts33476232023-01-30 19:57:29 +00007342 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007343
Prabir Pradhan678438e2023-04-13 19:32:51 +00007344 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7345 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007346
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007347 std::unique_ptr<KeyEvent> event = window->consumeKey();
7348 ASSERT_NE(event, nullptr);
7349 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007350 ASSERT_NE(verified, nullptr);
7351 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7352
7353 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7354 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7355 ASSERT_EQ(keyArgs.source, verified->source);
7356 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7357
7358 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7359
7360 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007361 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007362 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007363 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7364 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7365 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7366 ASSERT_EQ(0, verifiedKey.repeatCount);
7367}
7368
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007369TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007371 sp<FakeWindowHandle> window =
7372 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7373 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007374
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007375 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007376
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007377 ui::Transform transform;
7378 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7379
7380 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007381 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007382 displayInfo.transform = transform;
7383
Patrick Williamsd828f302023-04-28 17:52:08 -05007384 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007385
Prabir Pradhan678438e2023-04-13 19:32:51 +00007386 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007387 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007388 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007389 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007390
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007391 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7392 ASSERT_NE(nullptr, event);
7393 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007394 ASSERT_NE(verified, nullptr);
7395 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7396
7397 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7398 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7399 EXPECT_EQ(motionArgs.source, verified->source);
7400 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7401
7402 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7403
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007404 const vec2 rawXY =
7405 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7406 motionArgs.pointerCoords[0].getXYValue());
7407 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7408 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007409 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007410 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007411 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007412 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7413 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7414}
7415
chaviw09c8d2d2020-08-24 15:48:26 -07007416/**
7417 * Ensure that separate calls to sign the same data are generating the same key.
7418 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7419 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7420 * tests.
7421 */
7422TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7423 KeyEvent event = getTestKeyEvent();
7424 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7425
7426 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7427 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7428 ASSERT_EQ(hmac1, hmac2);
7429}
7430
7431/**
7432 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7433 */
7434TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7435 KeyEvent event = getTestKeyEvent();
7436 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7437 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7438
7439 verifiedEvent.deviceId += 1;
7440 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7441
7442 verifiedEvent.source += 1;
7443 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7444
7445 verifiedEvent.eventTimeNanos += 1;
7446 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7447
Linnan Li13bf76a2024-05-05 19:18:02 +08007448 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007449 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7450
7451 verifiedEvent.action += 1;
7452 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7453
7454 verifiedEvent.downTimeNanos += 1;
7455 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7456
7457 verifiedEvent.flags += 1;
7458 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7459
7460 verifiedEvent.keyCode += 1;
7461 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7462
7463 verifiedEvent.scanCode += 1;
7464 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7465
7466 verifiedEvent.metaState += 1;
7467 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7468
7469 verifiedEvent.repeatCount += 1;
7470 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7471}
7472
Vishnu Nair958da932020-08-21 17:12:37 -07007473TEST_F(InputDispatcherTest, SetFocusedWindow) {
7474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007475 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7476 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007477 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007478 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7479 ui::LogicalDisplayId::DEFAULT);
7480 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007481
7482 // Top window is also focusable but is not granted focus.
7483 windowTop->setFocusable(true);
7484 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007485 mDispatcher->onWindowInfosChanged(
7486 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007487 setFocusedWindow(windowSecond);
7488
7489 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007491 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007492
7493 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007494 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007495 windowTop->assertNoEvents();
7496}
7497
7498TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007500 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7501 ui::LogicalDisplayId::DEFAULT);
7502 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007503
7504 window->setFocusable(true);
7505 // Release channel for window is no longer valid.
7506 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007507 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007508 setFocusedWindow(window);
7509
7510 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007511 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007512
7513 // window channel is invalid, so it should not receive any input event.
7514 window->assertNoEvents();
7515}
7516
7517TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007519 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7520 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007521 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007522 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007523
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007524 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007525 setFocusedWindow(window);
7526
7527 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007528 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007529
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007530 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007531 window->assertNoEvents();
7532}
7533
7534TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7535 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007536 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7537 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007538 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007539 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7540 ui::LogicalDisplayId::DEFAULT);
7541 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007542
7543 windowTop->setFocusable(true);
7544 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007545 mDispatcher->onWindowInfosChanged(
7546 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007547 setFocusedWindow(windowTop);
7548 windowTop->consumeFocusEvent(true);
7549
Chavi Weingarten847e8512023-03-29 00:26:09 +00007550 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007551 mDispatcher->onWindowInfosChanged(
7552 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007553 windowSecond->consumeFocusEvent(true);
7554 windowTop->consumeFocusEvent(false);
7555
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007557 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007558
7559 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007560 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007561}
7562
Chavi Weingarten847e8512023-03-29 00:26:09 +00007563TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007565 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7566 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007567 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007568 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7569 ui::LogicalDisplayId::DEFAULT);
7570 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007571
7572 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007573 windowSecond->setFocusable(false);
7574 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007575 mDispatcher->onWindowInfosChanged(
7576 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007577 setFocusedWindow(windowTop);
7578 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007579
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007581 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007582
7583 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007584 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007585 windowSecond->assertNoEvents();
7586}
7587
7588TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7589 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007590 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7591 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007592 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007593 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007594 ui::LogicalDisplayId::DEFAULT);
7595 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007596
7597 window->setFocusable(true);
7598 previousFocusedWindow->setFocusable(true);
7599 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007600 mDispatcher->onWindowInfosChanged(
7601 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007602 setFocusedWindow(previousFocusedWindow);
7603 previousFocusedWindow->consumeFocusEvent(true);
7604
7605 // Requesting focus on invisible window takes focus from currently focused window.
7606 setFocusedWindow(window);
7607 previousFocusedWindow->consumeFocusEvent(false);
7608
7609 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007611 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007612 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007613
7614 // Window does not get focus event or key down.
7615 window->assertNoEvents();
7616
7617 // Window becomes visible.
7618 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007619 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007620
7621 // Window receives focus event.
7622 window->consumeFocusEvent(true);
7623 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007624 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007625}
7626
Vishnu Nair599f1412021-06-21 10:39:58 -07007627TEST_F(InputDispatcherTest, DisplayRemoved) {
7628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007629 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7630 ui::LogicalDisplayId::DEFAULT);
7631 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007632
7633 // window is granted focus.
7634 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007635 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007636 setFocusedWindow(window);
7637 window->consumeFocusEvent(true);
7638
7639 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007640 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007641 window->consumeFocusEvent(false);
7642}
7643
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007644/**
7645 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7646 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7647 * of the 'slipperyEnterWindow'.
7648 *
7649 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7650 * a way so that the touched location is no longer covered by the top window.
7651 *
7652 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7653 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7654 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7655 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7656 * with ACTION_DOWN).
7657 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7658 * window moved itself away from the touched location and had Flag::SLIPPERY.
7659 *
7660 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7661 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7662 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7663 *
7664 * In this test, we ensure that the event received by the bottom window has
7665 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7666 */
7667TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007668 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007669 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007670
7671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007672 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007673
7674 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007675 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7676 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007677 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007678 // Make sure this one overlaps the bottom window
7679 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7680 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7681 // one. Windows with the same owner are not considered to be occluding each other.
7682 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7683
7684 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007685 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7686 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007687 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007689 mDispatcher->onWindowInfosChanged(
7690 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007691
7692 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007693 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007694 AINPUT_SOURCE_TOUCHSCREEN,
7695 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007696 slipperyExitWindow->consumeMotionDown();
7697 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007698 mDispatcher->onWindowInfosChanged(
7699 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007700
Prabir Pradhan678438e2023-04-13 19:32:51 +00007701 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007702 AINPUT_SOURCE_TOUCHSCREEN,
7703 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007704
7705 slipperyExitWindow->consumeMotionCancel();
7706
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007707 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007708 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7709}
7710
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007711/**
7712 * Two windows, one on the left and another on the right. The left window is slippery. The right
7713 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
7714 * touch moves from the left window into the right window, the gesture should continue to go to the
7715 * left window. Touch shouldn't slip because the right window can't receive touches. This test
7716 * reproduces a crash.
7717 */
7718TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
7719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7720
7721 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007722 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7723 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007724 leftSlipperyWindow->setSlippery(true);
7725 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
7726
7727 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007728 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7729 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007730 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
7731 rightDropTouchesWindow->setDropInput(true);
7732
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007733 mDispatcher->onWindowInfosChanged(
7734 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007735
7736 // Start touch in the left window
7737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7738 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7739 .build());
7740 leftSlipperyWindow->consumeMotionDown();
7741
7742 // And move it into the right window
7743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7744 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7745 .build());
7746
7747 // Since the right window isn't eligible to receive input, touch does not slip.
7748 // The left window continues to receive the gesture.
7749 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7750 rightDropTouchesWindow->assertNoEvents();
7751}
7752
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007753/**
7754 * A single window is on screen first. Touch is injected into that window. Next, a second window
7755 * appears. Since the first window is slippery, touch will move from the first window to the second.
7756 */
7757TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7758 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7759 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007760 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
7761 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007762 originalWindow->setFrame(Rect(0, 0, 200, 200));
7763 originalWindow->setSlippery(true);
7764
7765 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007766 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
7767 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007768 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7769
7770 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7771
7772 // Touch down on the original window
7773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7774 injectMotionEvent(*mDispatcher,
7775 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7776 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7777 .build()));
7778 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7779
7780 // Now, a new window appears. This could be, for example, a notification shade that appears
7781 // after user starts to drag down on the launcher window.
7782 mDispatcher->onWindowInfosChanged(
7783 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7785 injectMotionEvent(*mDispatcher,
7786 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7787 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7788 .build()));
7789 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7790 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7792 injectMotionEvent(*mDispatcher,
7793 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7794 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7795 .build()));
7796 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7797
7798 originalWindow->assertNoEvents();
7799 appearingWindow->assertNoEvents();
7800}
7801
Linnan Li49b2b202024-04-12 12:46:40 +08007802/**
7803 * Three windows:
7804 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
7805 * - right window
7806 * - spy window
7807 * The three windows do not overlap.
7808 *
7809 * We have two devices reporting events:
7810 * - Device A reports ACTION_DOWN, which lands in the left window
7811 * - Device B reports ACTION_DOWN, which lands in the spy window.
7812 * - Now, device B reports ACTION_MOVE events which move to the right window.
7813 *
7814 * The right window should not receive any events because the spy window is not a foreground window,
7815 * and also it does not support slippery touches.
7816 */
7817TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
7818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7819 sp<FakeWindowHandle> leftWindow =
7820 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007821 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007822 leftWindow->setFrame(Rect(0, 0, 100, 100));
7823 leftWindow->setSlippery(true);
7824
7825 sp<FakeWindowHandle> rightWindow =
7826 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007827 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007828 rightWindow->setFrame(Rect(100, 0, 200, 100));
7829
7830 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007831 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
7832 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007833 spyWindow->setFrame(Rect(200, 0, 300, 100));
7834 spyWindow->setSpy(true);
7835 spyWindow->setTrustedOverlay(true);
7836
7837 mDispatcher->onWindowInfosChanged(
7838 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
7839
7840 const DeviceId deviceA = 9;
7841 const DeviceId deviceB = 3;
7842
7843 // Tap on left window with device A
7844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7845 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7846 .deviceId(deviceA)
7847 .build());
7848 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7849
7850 // Tap on spy window with device B
7851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7852 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7853 .deviceId(deviceB)
7854 .build());
7855 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7856
7857 // Move to right window with device B. Touches should not slip to the right window, because spy
7858 // window is not a foreground window, and it does not have FLAG_SLIPPERY
7859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7860 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7861 .deviceId(deviceB)
7862 .build());
7863 leftWindow->assertNoEvents();
7864 rightWindow->assertNoEvents();
7865 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7866}
7867
7868/**
7869 * Three windows arranged horizontally and without any overlap.
7870 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
7871 *
7872 * We have two devices reporting events:
7873 * - Device A reports ACTION_DOWN which lands in the left window
7874 * - Device B reports ACTION_DOWN which lands in the right window
7875 * - Device B reports ACTION_MOVE that shifts to the middle window.
7876 * This should cause touches for Device B to slip from the right window to the middle window.
7877 * The right window should receive ACTION_CANCEL for device B and the
7878 * middle window should receive down event for Device B.
7879 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
7880 */
7881TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07007882 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08007883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7884 sp<FakeWindowHandle> leftWindow =
7885 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007886 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007887 leftWindow->setFrame(Rect(0, 0, 100, 100));
7888 leftWindow->setSlippery(true);
7889
7890 sp<FakeWindowHandle> middleWindow =
7891 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007892 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007893 middleWindow->setFrame(Rect(100, 0, 200, 100));
7894
7895 sp<FakeWindowHandle> rightWindow =
7896 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007897 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007898 rightWindow->setFrame(Rect(200, 0, 300, 100));
7899 rightWindow->setSlippery(true);
7900
7901 mDispatcher->onWindowInfosChanged(
7902 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
7903 {},
7904 0,
7905 0});
7906
7907 const DeviceId deviceA = 9;
7908 const DeviceId deviceB = 3;
7909
7910 // Tap on left window with device A
7911 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7912 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7913 .deviceId(deviceA)
7914 .build());
7915 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7916
7917 // Tap on right window with device B
7918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7919 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7920 .deviceId(deviceB)
7921 .build());
7922 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7923
7924 // Move to middle window with device B. Touches should slip to middle window, because right
7925 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
7926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7927 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7928 .deviceId(deviceB)
7929 .build());
7930 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
7931 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7932
7933 // Move to middle window with device A. Touches should slip to middle window, because left
7934 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
7935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7936 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7937 .deviceId(deviceA)
7938 .build());
7939 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
7940 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7941
7942 // Ensure that middle window can receive the remaining move events.
7943 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7944 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
7945 .deviceId(deviceB)
7946 .build());
7947 leftWindow->assertNoEvents();
7948 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7949 rightWindow->assertNoEvents();
7950}
7951
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007952TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007953 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7955
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007956 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7957 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007958 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007959 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007960
7961 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007962 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
7963 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007964 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007965 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007966 rightSpy->setSpy(true);
7967 rightSpy->setTrustedOverlay(true);
7968
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007969 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7970 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007971 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007972 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007973
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007974 mDispatcher->onWindowInfosChanged(
7975 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007976
7977 // Touch in the left window
7978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7979 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7980 .build());
7981 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7982 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007983 ASSERT_NO_FATAL_FAILURE(
7984 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007985
7986 // Touch another finger over the right windows
7987 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7988 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7989 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7990 .build());
7991 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7992 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7993 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7994 mDispatcher->waitForIdle();
7995 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007996 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7997 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007998
7999 // Release finger over left window. The UP actions are not treated as device interaction.
8000 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8001 // is part of the UP action, we do not treat this as device interaction.
8002 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8003 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8004 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8005 .build());
8006 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8007 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8008 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8009 mDispatcher->waitForIdle();
8010 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8011
8012 // Move remaining finger
8013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8014 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8015 .build());
8016 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8017 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8018 mDispatcher->waitForIdle();
8019 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008020 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008021
8022 // Release all fingers
8023 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8024 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8025 .build());
8026 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8027 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8028 mDispatcher->waitForIdle();
8029 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8030}
8031
8032TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8033 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8034
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008035 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8036 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008037 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008038 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008039
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008040 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008041 setFocusedWindow(window);
8042 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8043
8044 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008045 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008046 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008047 ASSERT_NO_FATAL_FAILURE(
8048 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008049
8050 // The UP actions are not treated as device interaction.
8051 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008052 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008053 mDispatcher->waitForIdle();
8054 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8055}
8056
Prabir Pradhan5893d362023-11-17 04:30:40 +00008057TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8059
8060 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008061 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008062 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008063 sp<FakeWindowHandle> right =
8064 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8065 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008066 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008067 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8068 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008069 spy->setFrame(Rect(0, 0, 200, 100));
8070 spy->setTrustedOverlay(true);
8071 spy->setSpy(true);
8072
8073 mDispatcher->onWindowInfosChanged(
8074 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8075
8076 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008077 NotifyMotionArgs notifyArgs =
8078 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8079 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008080 mDispatcher->notifyMotion(notifyArgs);
8081
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008082 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008083 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8084 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008085 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008086 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8087 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008088 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008089 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8090
8091 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008092 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8093 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008094 mDispatcher->notifyMotion(notifyArgs);
8095
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008096 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008097 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8098 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008099 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008100 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8101 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008102 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008103 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8104
8105 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8106}
8107
Linnan Liccf6ce32024-04-11 20:32:13 +08008108/**
8109 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8110 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8111 * the previous window should receive this event and not be dropped.
8112 */
8113TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8114 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008115 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8116 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008117 window->setFrame(Rect(0, 0, 100, 100));
8118 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8119
8120 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8121 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8122 .build());
8123
8124 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8125
8126 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8127 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8128 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8129 .build());
8130
8131 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8132}
8133
8134/**
8135 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8136 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8137 * previous window should receive deviceB's event and it should be dropped.
8138 */
8139TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008141 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8142 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008143 window->setFrame(Rect(0, 0, 100, 100));
8144 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8145
8146 const DeviceId deviceA = 9;
8147 const DeviceId deviceB = 3;
8148
8149 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8150 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8151 .deviceId(deviceA)
8152 .build());
8153 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8154
8155 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8156 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8157 .deviceId(deviceB)
8158 .build());
8159 window->assertNoEvents();
8160}
8161
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008162class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8163protected:
8164 std::shared_ptr<FakeApplicationHandle> mApp;
8165 sp<FakeWindowHandle> mWindow;
8166
8167 virtual void SetUp() override {
8168 InputDispatcherTest::SetUp();
8169
8170 mApp = std::make_shared<FakeApplicationHandle>();
8171
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008172 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8173 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008174 mWindow->setFrame(Rect(0, 0, 100, 100));
8175
8176 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8177 setFocusedWindow(mWindow);
8178 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8179 }
8180
8181 void setFallback(int32_t keycode) {
8182 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8183 return KeyEventBuilder(event).keyCode(keycode).build();
8184 });
8185 }
8186
8187 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008188 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8189 ASSERT_NE(nullptr, event);
8190 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008191 }
8192};
8193
8194TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8195 mDispatcher->notifyKey(
8196 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8197 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8198 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8199}
8200
8201TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8202 mDispatcher->notifyKey(
8203 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8204 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8205 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8206}
8207
8208TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8209 mDispatcher->notifyKey(
8210 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8211
8212 // Do not handle this key event.
8213 consumeKey(/*handled=*/false,
8214 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8215 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8216
8217 // Since the policy did not request any fallback to be generated, ensure there are no events.
8218 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8219}
8220
8221TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8222 setFallback(AKEYCODE_B);
8223 mDispatcher->notifyKey(
8224 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8225
8226 // Do not handle this key event.
8227 consumeKey(/*handled=*/false,
8228 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8229
8230 // Since the key was not handled, ensure the fallback event was dispatched instead.
8231 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8232 consumeKey(/*handled=*/true,
8233 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8234 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8235
8236 // Release the original key, and ensure the fallback key is also released.
8237 mDispatcher->notifyKey(
8238 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8239 consumeKey(/*handled=*/false,
8240 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8241 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8242 consumeKey(/*handled=*/true,
8243 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8244 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8245
8246 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8247 mWindow->assertNoEvents();
8248}
8249
8250TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8251 setFallback(AKEYCODE_B);
8252 mDispatcher->notifyKey(
8253 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8254
8255 // Do not handle this key event, but handle the fallback.
8256 consumeKey(/*handled=*/false,
8257 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8258 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8259 consumeKey(/*handled=*/true,
8260 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8261 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8262
8263 // Release the original key, and ensure the fallback key is also released.
8264 mDispatcher->notifyKey(
8265 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8266 // But this time, the app handles the original key.
8267 consumeKey(/*handled=*/true,
8268 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8269 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8270 // Ensure the fallback key is canceled.
8271 consumeKey(/*handled=*/true,
8272 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8273 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8274
8275 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8276 mWindow->assertNoEvents();
8277}
8278
8279TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8280 setFallback(AKEYCODE_B);
8281 mDispatcher->notifyKey(
8282 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8283
8284 // Do not handle this key event.
8285 consumeKey(/*handled=*/false,
8286 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8287 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8288 // App does not handle the fallback either, so ensure another fallback is not generated.
8289 setFallback(AKEYCODE_C);
8290 consumeKey(/*handled=*/false,
8291 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8292 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8293
8294 // Release the original key, and ensure the fallback key is also released.
8295 setFallback(AKEYCODE_B);
8296 mDispatcher->notifyKey(
8297 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8298 consumeKey(/*handled=*/false,
8299 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8300 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8301 consumeKey(/*handled=*/false,
8302 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8303 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8304
8305 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8306 mWindow->assertNoEvents();
8307}
8308
8309TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8310 setFallback(AKEYCODE_B);
8311 mDispatcher->notifyKey(
8312 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8313
8314 // Do not handle this key event, so fallback is generated.
8315 consumeKey(/*handled=*/false,
8316 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8317 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8318 consumeKey(/*handled=*/true,
8319 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8320 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8321
8322 // Release the original key, but assume the policy is misbehaving and it
8323 // generates an inconsistent fallback to the one from the DOWN event.
8324 setFallback(AKEYCODE_C);
8325 mDispatcher->notifyKey(
8326 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8327 consumeKey(/*handled=*/false,
8328 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8329 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8330 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8331 consumeKey(/*handled=*/true,
8332 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8333 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8334
8335 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8336 mWindow->assertNoEvents();
8337}
8338
8339TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8340 setFallback(AKEYCODE_B);
8341 mDispatcher->notifyKey(
8342 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8343
8344 // Do not handle this key event, so fallback is generated.
8345 consumeKey(/*handled=*/false,
8346 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8347 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8348 consumeKey(/*handled=*/true,
8349 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8350 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8351
8352 // The original key is canceled.
8353 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8354 .keyCode(AKEYCODE_A)
8355 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8356 .build());
8357 consumeKey(/*handled=*/false,
8358 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8359 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8360 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8361 // Ensure the fallback key is also canceled due to the original key being canceled.
8362 consumeKey(/*handled=*/true,
8363 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8364 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8365
8366 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8367 mWindow->assertNoEvents();
8368}
8369
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008370TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008371 setFallback(AKEYCODE_B);
8372 mDispatcher->notifyKey(
8373 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8374
8375 // Do not handle this key event.
8376 consumeKey(/*handled=*/false,
8377 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8378 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8379 consumeKey(/*handled=*/true,
8380 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8381 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8382
8383 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8384 // When the unhandled key is reported to the policy next, remove the input channel.
8385 mDispatcher->removeInputChannel(mWindow->getToken());
8386 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8387 });
8388 // Release the original key, and let the app now handle the previously unhandled key.
8389 // This should result in the previously generated fallback key to be cancelled.
8390 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8391 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8392 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8393 // the policy call, we will now remove the input channel. Once the policy call returns, the
8394 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8395 // not cause any crashes.
8396 mDispatcher->notifyKey(
8397 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8398 consumeKey(/*handled=*/true,
8399 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8400 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8401}
8402
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008403TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8404 setFallback(AKEYCODE_B);
8405 mDispatcher->notifyKey(
8406 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8407
8408 // Do not handle this key event.
8409 consumeKey(/*handled=*/false,
8410 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8411 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8412 consumeKey(/*handled=*/true,
8413 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8414 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8415
8416 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8417 // When the unhandled key is reported to the policy next, remove the window.
8418 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8419 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8420 });
8421 // Release the original key, which the app will not handle. When this unhandled key is reported
8422 // to the policy, the window will be removed.
8423 mDispatcher->notifyKey(
8424 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8425 consumeKey(/*handled=*/false,
8426 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8427 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8428
8429 // Since the window was removed, it loses focus, and the channel state will be reset.
8430 consumeKey(/*handled=*/true,
8431 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8432 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8433 mWindow->consumeFocusEvent(false);
8434 mWindow->assertNoEvents();
8435}
8436
8437TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8438 setFallback(AKEYCODE_B);
8439 mDispatcher->notifyKey(
8440 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8441
8442 // Do not handle this key event.
8443 consumeKey(/*handled=*/false,
8444 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8445 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8446 const auto [seq, event] = mWindow->receiveEvent();
8447 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8448 ASSERT_EQ(event->getType(), InputEventType::KEY);
8449 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8450 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8451 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8452
8453 // Remove the window now, which should generate a cancellations and make the window lose focus.
8454 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8455 consumeKey(/*handled=*/true,
8456 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8457 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8458 consumeKey(/*handled=*/true,
8459 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8460 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8461 mWindow->consumeFocusEvent(false);
8462
8463 // Finish the event by reporting it as handled.
8464 mWindow->finishEvent(*seq);
8465 mWindow->assertNoEvents();
8466}
8467
Garfield Tan1c7bc862020-01-28 13:24:04 -08008468class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8469protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008470 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8471 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008472
Chris Yea209fde2020-07-22 13:54:51 -07008473 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008474 sp<FakeWindowHandle> mWindow;
8475
8476 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008477 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008478
Prabir Pradhandae52792023-12-15 07:36:40 +00008479 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008480 setUpWindow();
8481 }
8482
8483 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008484 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008485 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8486 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008487
Vishnu Nair47074b82020-08-14 11:54:47 -07008488 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008489 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008490 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008491 mWindow->consumeFocusEvent(true);
8492 }
8493
Chris Ye2ad95392020-09-01 13:44:44 -07008494 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008495 NotifyKeyArgs keyArgs =
8496 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008497 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008498 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008499 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008500
8501 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008502 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008503 }
8504
8505 void expectKeyRepeatOnce(int32_t repeatCount) {
8506 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008507 mWindow->consumeKeyEvent(
8508 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008509 }
8510
Chris Ye2ad95392020-09-01 13:44:44 -07008511 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008512 NotifyKeyArgs keyArgs =
8513 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008514 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008515 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008516 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008517
8518 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008519 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008520 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008521 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008522
8523 void injectKeyRepeat(int32_t repeatCount) {
8524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008525 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8526 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008527 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8528 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008529};
8530
8531TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008532 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008533 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8534 expectKeyRepeatOnce(repeatCount);
8535 }
8536}
8537
8538TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008539 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008540 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8541 expectKeyRepeatOnce(repeatCount);
8542 }
Harry Cutts33476232023-01-30 19:57:29 +00008543 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008544 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008545 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8546 expectKeyRepeatOnce(repeatCount);
8547 }
8548}
8549
8550TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008551 sendAndConsumeKeyDown(/*deviceId=*/1);
8552 expectKeyRepeatOnce(/*repeatCount=*/1);
8553 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008554 mWindow->assertNoEvents();
8555}
8556
8557TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008558 sendAndConsumeKeyDown(/*deviceId=*/1);
8559 expectKeyRepeatOnce(/*repeatCount=*/1);
8560 sendAndConsumeKeyDown(/*deviceId=*/2);
8561 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008562 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008563 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008564 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008565 expectKeyRepeatOnce(/*repeatCount=*/2);
8566 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008567 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008568 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008569 mWindow->assertNoEvents();
8570}
8571
8572TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008573 sendAndConsumeKeyDown(/*deviceId=*/1);
8574 expectKeyRepeatOnce(/*repeatCount=*/1);
8575 sendAndConsumeKeyDown(/*deviceId=*/2);
8576 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008577 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008578 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008579 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008580 mWindow->assertNoEvents();
8581}
8582
liushenxiang42232912021-05-21 20:24:09 +08008583TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8584 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008585 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008586 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008587 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008588 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8589 mWindow->assertNoEvents();
8590}
8591
Garfield Tan1c7bc862020-01-28 13:24:04 -08008592TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008593 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008594 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008595 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008596 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8597 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008598 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008599 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008600 }
8601}
8602
8603TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008604 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008605 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008606
8607 std::unordered_set<int32_t> idSet;
8608 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008609 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8610 ASSERT_NE(nullptr, repeatEvent);
8611 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008612 EXPECT_EQ(idSet.end(), idSet.find(id));
8613 idSet.insert(id);
8614 }
8615}
8616
Hu Guofe3c8f12023-09-22 17:20:15 +08008617TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8618 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008619 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008620 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8621 expectKeyRepeatOnce(repeatCount);
8622 }
8623 injectKeyRepeat(1);
8624 // Expect repeatCount to be 3 instead of 1
8625 expectKeyRepeatOnce(3);
8626}
8627
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008628/* Test InputDispatcher for MultiDisplay */
8629class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8630public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008631 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008632 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008633
Chris Yea209fde2020-07-22 13:54:51 -07008634 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008635 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8636 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008637
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008638 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008639 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008640 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008641 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8642
Vishnu Nair958da932020-08-21 17:12:37 -07008643 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008644 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008645
Chris Yea209fde2020-07-22 13:54:51 -07008646 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008647 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008648 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008649 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008650 // Set focus display to second one.
8651 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00008652 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
8653
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008654 // Set focus window for second display.
8655 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008656 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008657 mDispatcher->onWindowInfosChanged(
8658 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008659 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008660 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008661 }
8662
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008663 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008664 InputDispatcherTest::TearDown();
8665
Chris Yea209fde2020-07-22 13:54:51 -07008666 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008667 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008668 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008669 windowInSecondary.clear();
8670 }
8671
8672protected:
Chris Yea209fde2020-07-22 13:54:51 -07008673 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008674 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008675 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008676 sp<FakeWindowHandle> windowInSecondary;
8677};
8678
8679TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8680 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008682 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8683 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008685 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008686 windowInSecondary->assertNoEvents();
8687
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008688 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008690 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008692 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008693 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008694}
8695
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008696TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008697 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008699 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008700 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008701 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08008702 windowInSecondary->assertNoEvents();
8703
8704 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008706 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008707 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008708 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008709
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008710 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008711 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08008712
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008713 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008714 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08008715
8716 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008717 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08008718 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008719 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08008720 windowInSecondary->assertNoEvents();
8721}
8722
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008723// Test per-display input monitors for motion event.
8724TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08008725 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008726 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008727 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008728 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008729
8730 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008732 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8733 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008735 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8736 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008737 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008738 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008739
8740 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008742 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008744 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008745 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008746 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08008747 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008748
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008749 // Lift up the touch from the second display
8750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008751 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8753 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
8754 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
8755
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008756 // Test inject a non-pointer motion event.
8757 // If specific a display, it will dispatch to the focused window of particular display,
8758 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
8761 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008763 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008764 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008765 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
8766 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008767}
8768
8769// Test per-display input monitors for key event.
8770TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008771 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08008772 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008773 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008774 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008775 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008776
8777 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008779 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008780 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008781 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008782 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8783 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008784}
8785
Vishnu Nair958da932020-08-21 17:12:37 -07008786TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
8787 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008788 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
8789 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008790 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008791 mDispatcher->onWindowInfosChanged(
8792 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
8793 *windowInSecondary->getInfo()},
8794 {},
8795 0,
8796 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008797 setFocusedWindow(secondWindowInPrimary);
8798 windowInPrimary->consumeFocusEvent(false);
8799 secondWindowInPrimary->consumeFocusEvent(true);
8800
8801 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008803 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008804 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008805 windowInPrimary->assertNoEvents();
8806 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008807 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008808}
8809
Arthur Hungdfd528e2021-12-08 13:23:04 +00008810TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
8811 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008812 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008813 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008814 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008815
8816 // Test touch down on primary display.
8817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008818 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8819 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008821 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8822 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008823
8824 // Test touch down on second display.
8825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008826 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8828 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
8829 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
8830
8831 // Trigger cancel touch.
8832 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008833 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
8834 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008835 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
8836 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
8837
8838 // Test inject a move motion event, no window/monitor should receive the event.
8839 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008840 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008841 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008842 << "Inject motion event should return InputEventInjectionResult::FAILED";
8843 windowInPrimary->assertNoEvents();
8844 monitorInPrimary.assertNoEvents();
8845
8846 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008847 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00008848 SECOND_DISPLAY_ID, {110, 200}))
8849 << "Inject motion event should return InputEventInjectionResult::FAILED";
8850 windowInSecondary->assertNoEvents();
8851 monitorInSecondary.assertNoEvents();
8852}
8853
Hu Guocb134f12023-12-23 13:42:44 +00008854/**
8855 * Send a key to the primary display and to the secondary display.
8856 * Then cause the key on the primary display to be canceled by sending in a stale key.
8857 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
8858 * does not get canceled.
8859 */
8860TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
8861 // Send a key down on primary display
8862 mDispatcher->notifyKey(
8863 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008864 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008865 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8866 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008867 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
8868 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008869 windowInSecondary->assertNoEvents();
8870
8871 // Send a key down on second display
8872 mDispatcher->notifyKey(
8873 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8874 .displayId(SECOND_DISPLAY_ID)
8875 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8876 .build());
8877 windowInSecondary->consumeKeyEvent(
8878 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8879 windowInPrimary->assertNoEvents();
8880
8881 // Send a valid key up event on primary display that will be dropped because it is stale
8882 NotifyKeyArgs staleKeyUp =
8883 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008884 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008885 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8886 .build();
8887 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8888 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8889 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8890 mDispatcher->notifyKey(staleKeyUp);
8891
8892 // Only the key gesture corresponding to the dropped event should receive the cancel event.
8893 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
8894 // receive any events.
8895 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008896 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00008897 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8898 windowInSecondary->assertNoEvents();
8899}
8900
8901/**
8902 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
8903 */
8904TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
8905 // Send touch down on primary display.
8906 mDispatcher->notifyMotion(
8907 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8908 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008909 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008910 .build());
8911 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008912 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008913 windowInSecondary->assertNoEvents();
8914
8915 // Send touch down on second display.
8916 mDispatcher->notifyMotion(
8917 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8918 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8919 .displayId(SECOND_DISPLAY_ID)
8920 .build());
8921 windowInPrimary->assertNoEvents();
8922 windowInSecondary->consumeMotionEvent(
8923 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8924
8925 // inject a valid MotionEvent on primary display that will be stale when it arrives.
8926 NotifyMotionArgs staleMotionUp =
8927 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008928 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008929 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8930 .build();
8931 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8932 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8933 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8934 mDispatcher->notifyMotion(staleMotionUp);
8935
8936 // For stale motion events, we let the gesture to complete. This behaviour is different from key
8937 // events, where we would cancel the current keys instead.
8938 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
8939 windowInSecondary->assertNoEvents();
8940}
8941
Jackal Guof9696682018-10-05 12:23:23 +08008942class InputFilterTest : public InputDispatcherTest {
8943protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08008944 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008945 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08008946 NotifyMotionArgs motionArgs;
8947
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008948 motionArgs =
8949 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008950 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008951 motionArgs =
8952 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008953 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008954 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008955 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008956 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008957 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08008958 } else {
8959 mFakePolicy->assertFilterInputEventWasNotCalled();
8960 }
8961 }
8962
8963 void testNotifyKey(bool expectToBeFiltered) {
8964 NotifyKeyArgs keyArgs;
8965
8966 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008967 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008968 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008969 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008970 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008971
8972 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08008973 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008974 } else {
8975 mFakePolicy->assertFilterInputEventWasNotCalled();
8976 }
8977 }
8978};
8979
8980// Test InputFilter for MotionEvent
8981TEST_F(InputFilterTest, MotionEvent_InputFilter) {
8982 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008983 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008984 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008985
8986 // Enable InputFilter
8987 mDispatcher->setInputFilterEnabled(true);
8988 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008989 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008990 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008991
8992 // Disable InputFilter
8993 mDispatcher->setInputFilterEnabled(false);
8994 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008995 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008996 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008997}
8998
8999// Test InputFilter for KeyEvent
9000TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9001 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009002 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009003
9004 // Enable InputFilter
9005 mDispatcher->setInputFilterEnabled(true);
9006 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009007 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009008
9009 // Disable InputFilter
9010 mDispatcher->setInputFilterEnabled(false);
9011 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009012 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009013}
9014
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009015// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9016// logical display coordinate space.
9017TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9018 ui::Transform firstDisplayTransform;
9019 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9020 ui::Transform secondDisplayTransform;
9021 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9022
9023 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009024 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009025 displayInfos[0].transform = firstDisplayTransform;
9026 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9027 displayInfos[1].transform = secondDisplayTransform;
9028
Patrick Williamsd828f302023-04-28 17:52:08 -05009029 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009030
9031 // Enable InputFilter
9032 mDispatcher->setInputFilterEnabled(true);
9033
9034 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009035 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9036 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009037 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009038}
9039
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009040class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9041protected:
9042 virtual void SetUp() override {
9043 InputDispatcherTest::SetUp();
9044
9045 /**
9046 * We don't need to enable input filter to test the injected event policy, but we enabled it
9047 * here to make the tests more realistic, since this policy only matters when inputfilter is
9048 * on.
9049 */
9050 mDispatcher->setInputFilterEnabled(true);
9051
9052 std::shared_ptr<InputApplicationHandle> application =
9053 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009054 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009055 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009056
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009057 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009058 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009059 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009060 setFocusedWindow(mWindow);
9061 mWindow->consumeFocusEvent(true);
9062 }
9063
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009064 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9065 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009066 KeyEvent event;
9067
9068 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9069 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009070 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9071 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009072 const int32_t additionalPolicyFlags =
9073 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009075 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009076 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009077 policyFlags | additionalPolicyFlags));
9078
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009079 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009080 }
9081
9082 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9083 int32_t flags) {
9084 MotionEvent event;
9085 PointerProperties pointerProperties[1];
9086 PointerCoords pointerCoords[1];
9087 pointerProperties[0].clear();
9088 pointerProperties[0].id = 0;
9089 pointerCoords[0].clear();
9090 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9091 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9092
9093 ui::Transform identityTransform;
9094 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9095 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9096 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9097 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9098 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009099 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009100 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009101 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009102
9103 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009105 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009106 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009107 policyFlags | additionalPolicyFlags));
9108
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009109 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009110 }
9111
9112private:
9113 sp<FakeWindowHandle> mWindow;
9114};
9115
9116TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009117 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9118 // filter. Without it, the event will no different from a regularly injected event, and the
9119 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009120 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9121 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009122}
9123
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009124TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009125 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009126 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009127 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9128}
9129
9130TEST_F(InputFilterInjectionPolicyTest,
9131 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9132 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009133 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009134 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009135}
9136
9137TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009138 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9139 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009140}
9141
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009142class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9143protected:
9144 virtual void SetUp() override {
9145 InputDispatcherTest::SetUp();
9146
9147 std::shared_ptr<FakeApplicationHandle> application =
9148 std::make_shared<FakeApplicationHandle>();
9149 application->setDispatchingTimeout(100ms);
9150 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009151 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009152 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009153 mWindow->setDispatchingTimeout(100ms);
9154 mWindow->setFocusable(true);
9155
9156 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009157 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009158
9159 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9160 setFocusedWindow(mWindow);
9161 mWindow->consumeFocusEvent(true);
9162 }
9163
Linnan Li13bf76a2024-05-05 19:18:02 +08009164 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009165 nsecs_t eventTime) {
9166 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9167 .displayId(displayId)
9168 .eventTime(eventTime)
9169 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9170 .build());
9171 mWindow->consumeMotionEvent(WithMotionAction(action));
9172 }
9173
9174private:
9175 sp<FakeWindowHandle> mWindow;
9176};
9177
9178TEST_F_WITH_FLAGS(
9179 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9180 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9181 rate_limit_user_activity_poke_in_dispatcher))) {
9182 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9183
9184 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009185 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009186 milliseconds_to_nanoseconds(50));
9187 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009188 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9189 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009190
9191 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009192 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009193 milliseconds_to_nanoseconds(130));
9194 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009195 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9196 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009197
9198 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009199 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9200 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009201 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009202 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9203 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009204
9205 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009206 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009207 milliseconds_to_nanoseconds(140));
9208 mFakePolicy->assertUserActivityNotPoked();
9209
9210 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009211 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9212 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009213 mFakePolicy->assertUserActivityNotPoked();
9214
9215 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9216 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009217 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009218 milliseconds_to_nanoseconds(160));
9219 mFakePolicy->assertUserActivityNotPoked();
9220
9221 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009222 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9223 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009224 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009225 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9226 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009227
9228 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009229 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009230 milliseconds_to_nanoseconds(300));
9231 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009232 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9233 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009234
9235 // Assert that there's no more user activity poke event.
9236 mFakePolicy->assertUserActivityNotPoked();
9237}
9238
9239TEST_F_WITH_FLAGS(
9240 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9241 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9242 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009243 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009244 milliseconds_to_nanoseconds(200));
9245 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009246 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9247 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009248
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009249 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009250 milliseconds_to_nanoseconds(280));
9251 mFakePolicy->assertUserActivityNotPoked();
9252
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009253 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009254 milliseconds_to_nanoseconds(340));
9255 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009256 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9257 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009258}
9259
9260TEST_F_WITH_FLAGS(
9261 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9262 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9263 rate_limit_user_activity_poke_in_dispatcher))) {
9264 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9265
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009266 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9267 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009268 mFakePolicy->assertUserActivityPoked();
9269
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009270 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9271 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009272 mFakePolicy->assertUserActivityPoked();
9273}
9274
chaviwfd6d3512019-03-25 13:23:49 -07009275class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009276 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009277 InputDispatcherTest::SetUp();
9278
Chris Yea209fde2020-07-22 13:54:51 -07009279 std::shared_ptr<FakeApplicationHandle> application =
9280 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009281 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9282 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009283 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009284
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009285 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9286 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009287 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009288
9289 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009290 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009291 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009292
9293 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009294 mDispatcher->onWindowInfosChanged(
9295 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009296 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009297 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009298 }
9299
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009300 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009301 InputDispatcherTest::TearDown();
9302
9303 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009304 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009305 }
9306
9307protected:
9308 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009309 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009310 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009311};
9312
9313// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9314// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9315// the onPointerDownOutsideFocus callback.
9316TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009318 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9319 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009321 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009322
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009323 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009324 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9325}
9326
9327// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9328// DOWN on the window that doesn't have focus. Ensure no window received the
9329// onPointerDownOutsideFocus callback.
9330TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009332 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009333 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009335 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009336
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009337 ASSERT_TRUE(mDispatcher->waitForIdle());
9338 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009339}
9340
9341// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9342// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9343TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009345 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009346 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009347 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009348
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009349 ASSERT_TRUE(mDispatcher->waitForIdle());
9350 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009351}
9352
9353// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9354// DOWN on the window that already has focus. Ensure no window received the
9355// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009356TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009358 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9359 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009361 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009362
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009363 ASSERT_TRUE(mDispatcher->waitForIdle());
9364 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009365}
9366
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009367// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9368// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9369TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9370 const MotionEvent event =
9371 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9372 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009373 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009374 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9375 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009377 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009378 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9379 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009380
9381 ASSERT_TRUE(mDispatcher->waitForIdle());
9382 mFakePolicy->assertOnPointerDownWasNotCalled();
9383 // Ensure that the unfocused window did not receive any FOCUS events.
9384 mUnfocusedWindow->assertNoEvents();
9385}
9386
chaviwaf87b3e2019-10-01 16:59:28 -07009387// These tests ensures we can send touch events to a single client when there are multiple input
9388// windows that point to the same client token.
9389class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9390 virtual void SetUp() override {
9391 InputDispatcherTest::SetUp();
9392
Chris Yea209fde2020-07-22 13:54:51 -07009393 std::shared_ptr<FakeApplicationHandle> application =
9394 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009395 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009396 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009397 mWindow1->setFrame(Rect(0, 0, 100, 100));
9398
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009399 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009400 mWindow2->setFrame(Rect(100, 100, 200, 200));
9401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009402 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009403 }
9404
9405protected:
9406 sp<FakeWindowHandle> mWindow1;
9407 sp<FakeWindowHandle> mWindow2;
9408
9409 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009410 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009411 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9412 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009413 }
9414
9415 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9416 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009417 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009418 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009419 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009420 ASSERT_NE(nullptr, motionEvent);
9421 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009422
9423 for (size_t i = 0; i < points.size(); i++) {
9424 float expectedX = points[i].x;
9425 float expectedY = points[i].y;
9426
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009427 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009428 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009429 << ", got " << motionEvent->getX(i);
9430 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009431 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009432 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009433 }
9434 }
chaviw9eaa22c2020-07-01 16:21:27 -07009435
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009436 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9437 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009438 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009439 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009440 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009441
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009442 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009443 }
chaviwaf87b3e2019-10-01 16:59:28 -07009444};
9445
9446TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9447 // Touch Window 1
9448 PointF touchedPoint = {10, 10};
9449 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009450 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009451
9452 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009453 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009454
9455 // Touch Window 2
9456 touchedPoint = {150, 150};
9457 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009458 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009459}
9460
chaviw9eaa22c2020-07-01 16:21:27 -07009461TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9462 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009463 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009464 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009465
9466 // Touch Window 1
9467 PointF touchedPoint = {10, 10};
9468 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009469 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009470 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009471 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009472
9473 // Touch Window 2
9474 touchedPoint = {150, 150};
9475 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009476 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9477 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009478
chaviw9eaa22c2020-07-01 16:21:27 -07009479 // Update the transform so rotation is set
9480 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009481 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009482 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009483 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009484}
9485
chaviw9eaa22c2020-07-01 16:21:27 -07009486TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009487 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009488 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009489
9490 // Touch Window 1
9491 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9492 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009493 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009494
9495 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009496 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9497 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9498 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009499 touchedPoints.push_back(PointF{150, 150});
9500 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009501 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009502
chaviw9eaa22c2020-07-01 16:21:27 -07009503 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009504 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009505 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009506
chaviw9eaa22c2020-07-01 16:21:27 -07009507 // Update the transform so rotation is set for Window 2
9508 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009509 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009510 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009511 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009512}
9513
chaviw9eaa22c2020-07-01 16:21:27 -07009514TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009515 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009516 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009517
9518 // Touch Window 1
9519 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9520 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009521 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009522
9523 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009524 touchedPoints.push_back(PointF{150, 150});
9525 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009526
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009527 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009528
9529 // Move both windows
9530 touchedPoints = {{20, 20}, {175, 175}};
9531 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9532 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9533
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009534 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009535
chaviw9eaa22c2020-07-01 16:21:27 -07009536 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009537 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009538 expectedPoints.pop_back();
9539
9540 // Touch Window 2
9541 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009542 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009543 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009544 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009545
9546 // Move both windows
9547 touchedPoints = {{20, 20}, {175, 175}};
9548 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9549 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9550
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009551 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009552}
9553
9554TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9555 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009556 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009557
9558 // Touch Window 1
9559 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9560 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009561 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009562
9563 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009564 touchedPoints.push_back(PointF{150, 150});
9565 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009566
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009567 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009568
9569 // Move both windows
9570 touchedPoints = {{20, 20}, {175, 175}};
9571 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9572 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9573
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009574 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009575}
9576
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009577/**
9578 * When one of the windows is slippery, the touch should not slip into the other window with the
9579 * same input channel.
9580 */
9581TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9582 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009583 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009584
9585 // Touch down in window 1
9586 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009587 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009588 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9589
9590 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9591 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9592 // getting generated.
9593 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009594 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009595
9596 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9597}
9598
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009599/**
9600 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9601 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9602 * that the pointer is hovering over may have a different transform.
9603 */
9604TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009605 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009606
9607 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9609 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9610 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009611 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9612 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009613 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009614 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9615 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9616 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009617 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009618 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009619 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9620}
9621
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009622class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9623 virtual void SetUp() override {
9624 InputDispatcherTest::SetUp();
9625
Chris Yea209fde2020-07-22 13:54:51 -07009626 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009627 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009628 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009629 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009630 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009631 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009632 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009633
9634 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009635 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009636
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009637 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009638 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009639 mWindow->consumeFocusEvent(true);
9640 }
9641
9642 virtual void TearDown() override {
9643 InputDispatcherTest::TearDown();
9644 mWindow.clear();
9645 }
9646
9647protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009648 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009649 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009650 sp<FakeWindowHandle> mWindow;
9651 static constexpr PointF WINDOW_LOCATION = {20, 20};
9652
9653 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009654 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9655 .x(WINDOW_LOCATION.x)
9656 .y(WINDOW_LOCATION.y);
9657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9658 .pointer(touchingPointer)
9659 .build());
9660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9661 .pointer(touchingPointer)
9662 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009663 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009664
9665 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009666 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9667 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009668 spy->setTrustedOverlay(true);
9669 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009670 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009671 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009672 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009673 return spy;
9674 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009675};
9676
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009677// Send a tap and respond, which should not cause an ANR.
9678TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9679 tapOnWindow();
9680 mWindow->consumeMotionDown();
9681 mWindow->consumeMotionUp();
9682 ASSERT_TRUE(mDispatcher->waitForIdle());
9683 mFakePolicy->assertNotifyAnrWasNotCalled();
9684}
9685
9686// Send a regular key and respond, which should not cause an ANR.
9687TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009689 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009690 ASSERT_TRUE(mDispatcher->waitForIdle());
9691 mFakePolicy->assertNotifyAnrWasNotCalled();
9692}
9693
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009694TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9695 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009696 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009697 mWindow->consumeFocusEvent(false);
9698
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009699 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009700 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9701 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
9702 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00009703 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009705 // Key will not go to window because we have no focused window.
9706 // The 'no focused window' ANR timer should start instead.
9707
9708 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009709 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009710 // The key should get dropped and there should be no ANR.
9711
9712 ASSERT_TRUE(mDispatcher->waitForIdle());
9713 mFakePolicy->assertNotifyAnrWasNotCalled();
9714}
9715
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009716// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009717// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9718// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009719TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9722 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009723
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009724 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009725 ASSERT_TRUE(sequenceNum);
9726 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009727 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009728
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009729 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009730 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009731 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009732 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009733 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009734}
9735
9736// Send a key to the app and have the app not respond right away.
9737TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
9738 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009740 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009741 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009742 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009743 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009744 ASSERT_TRUE(mDispatcher->waitForIdle());
9745}
9746
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009747// We have a focused application, but no focused window
9748TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009749 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009750 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009751 mWindow->consumeFocusEvent(false);
9752
9753 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009755 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9756 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009757 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9758 mDispatcher->waitForIdle();
9759 mFakePolicy->assertNotifyAnrWasNotCalled();
9760
9761 // Once a focused event arrives, we get an ANR for this application
9762 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9763 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009764 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009765 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9766 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +08009767 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009768 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009769 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07009770 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009771 ASSERT_TRUE(mDispatcher->waitForIdle());
9772}
9773
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009774/**
9775 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
9776 * there will not be an ANR.
9777 */
9778TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
9779 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009780 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009781 mWindow->consumeFocusEvent(false);
9782
9783 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07009784 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
9785 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009786 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
9787 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
9788
9789 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009790 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
9791 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
9792 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
9793 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009794
Hu Guofe3c8f12023-09-22 17:20:15 +08009795 const int32_t policyFlags =
9796 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009797
9798 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00009799 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009800 InputEventInjectionSync::WAIT_FOR_RESULT,
9801 INJECT_EVENT_TIMEOUT, policyFlags);
9802 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
9803 << "Injection should fail because the event is stale";
9804
9805 ASSERT_TRUE(mDispatcher->waitForIdle());
9806 mFakePolicy->assertNotifyAnrWasNotCalled();
9807 mWindow->assertNoEvents();
9808}
9809
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009810// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009811// Make sure that we don't notify policy twice about the same ANR.
9812TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009813 const std::chrono::duration appTimeout = 400ms;
9814 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009815 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009816
Vishnu Nair47074b82020-08-14 11:54:47 -07009817 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009818 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009819 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009820
9821 // Once a focused event arrives, we get an ANR for this application
9822 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9823 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009824 const std::chrono::duration eventInjectionTimeout = 100ms;
9825 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009826 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009827 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9828 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
9829 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009830 /*allowKeyRepeat=*/false);
9831 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
9832 << "result=" << ftl::enum_string(result);
9833 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
9834 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
9835 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
9836 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009837
Vishnu Naire4df8752022-09-08 09:17:55 -07009838 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009839 // ANR should not be raised again. It is up to policy to do that if it desires.
9840 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009841
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009842 // If we now get a focused window, the ANR should stop, but the policy handles that via
9843 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009844 ASSERT_TRUE(mDispatcher->waitForIdle());
9845}
9846
9847// We have a focused application, but no focused window
9848TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009849 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009850 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009851 mWindow->consumeFocusEvent(false);
9852
9853 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009854 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009855
Vishnu Naire4df8752022-09-08 09:17:55 -07009856 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9857 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009858
9859 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009860 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009861 ASSERT_TRUE(mDispatcher->waitForIdle());
9862 mWindow->assertNoEvents();
9863}
9864
9865/**
9866 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
9867 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
9868 * If we process 1 of the events, but ANR on the second event with the same timestamp,
9869 * the ANR mechanism should still work.
9870 *
9871 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
9872 * DOWN event, while not responding on the second one.
9873 */
9874TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
9875 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009876 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009877 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009878 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9879 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009880 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009881
9882 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009883 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009884 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009885 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9886 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009887 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009888
9889 // We have now sent down and up. Let's consume first event and then ANR on the second.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009890 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009891 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009892 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009893}
9894
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009895// A spy window can receive an ANR
9896TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
9897 sp<FakeWindowHandle> spy = addSpyWindow();
9898
9899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009900 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9901 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009902 mWindow->consumeMotionDown();
9903
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009904 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009905 ASSERT_TRUE(sequenceNum);
9906 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009907 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009908
9909 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009910 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009911 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009912 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009913 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009914}
9915
9916// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009917// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009918TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
9919 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009920
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009922 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
9923 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9925 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009926
9927 // Stuck on the ACTION_UP
9928 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009929 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009930
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009931 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009932 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009933 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9934 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009935
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009936 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009937 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009938 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009939 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009940 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009941}
9942
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009943// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009944// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009945TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
9946 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009947
9948 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009949 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9950 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009951
9952 mWindow->consumeMotionDown();
9953 // Stuck on the ACTION_UP
9954 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009955 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009956
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009957 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009958 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009959 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9960 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009961
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009962 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009963 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009964 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009965 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009966 spy->assertNoEvents();
9967}
9968
9969TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009970 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009971
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009972 FakeMonitorReceiver monitor =
9973 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009974
9975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009976 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9977 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009978
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009979 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009980 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
9981 ASSERT_TRUE(consumeSeq);
9982
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009983 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
9984 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009985
9986 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009987 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009988
9989 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009990 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009991}
9992
9993// If a window is unresponsive, then you get anr. if the window later catches up and starts to
9994// process events, you don't get an anr. When the window later becomes unresponsive again, you
9995// get an ANR again.
9996// 1. tap -> block on ACTION_UP -> receive ANR
9997// 2. consume all pending events (= queue becomes healthy again)
9998// 3. tap again -> block on ACTION_UP again -> receive ANR second time
9999TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10000 tapOnWindow();
10001
10002 mWindow->consumeMotionDown();
10003 // Block on ACTION_UP
10004 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010005 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010006 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10007 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010008 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010009 mWindow->assertNoEvents();
10010
10011 tapOnWindow();
10012 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010013 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010014 mWindow->consumeMotionUp();
10015
10016 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010017 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010018 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010019 mWindow->assertNoEvents();
10020}
10021
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010022// If a connection remains unresponsive for a while, make sure policy is only notified once about
10023// it.
10024TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010026 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10027 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010028
10029 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010030 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010031 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010032 // 'notifyConnectionUnresponsive' should only be called once per connection
10033 mFakePolicy->assertNotifyAnrWasNotCalled();
10034 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010035 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010036 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010037 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010038 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010039 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010040 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010041 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010042}
10043
10044/**
10045 * 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 -070010046 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010047 */
10048TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010049 // The timeouts in this test are established by relying on the fact that the "key waiting for
10050 // events timeout" is equal to 500ms.
10051 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010052 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010053 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010054
10055 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010056 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010057 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010058 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010059 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010060
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010061 // Don't finish the events yet, and send a key
10062 mDispatcher->notifyKey(
10063 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10064 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10065 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010066 // Key will not be sent to the window, yet, because the window is still processing events
10067 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010068 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010069 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010070
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010071 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010072 // if we wait long enough though, dispatcher will give up, and still send the key
10073 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010074 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010075 mWindow->finishEvent(*downSequenceNum);
10076 mWindow->finishEvent(*upSequenceNum);
10077}
10078
10079/**
10080 * If a window is processing a motion event, and then a key event comes in, the key event should
10081 * not go to the focused window until the motion is processed.
10082 * If then a new motion comes in, then the pending key event should be going to the currently
10083 * focused window right away.
10084 */
10085TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010086 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10087 // The timeouts in this test are established by relying on the fact that the "key waiting for
10088 // events timeout" is equal to 500ms.
10089 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010090 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010091 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010092
10093 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010094 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010095 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010096 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010097 ASSERT_TRUE(upSequenceNum);
10098 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010099 mDispatcher->notifyKey(
10100 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10101 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10102 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010103 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010104 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010105
10106 // Now tap down again. It should cause the pending key to go to the focused window right away.
10107 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010108 // Now that we tapped, we should receive the key immediately.
10109 // Since there's still room for slowness, we use 200ms, which is much less than
10110 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10111 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10112 ASSERT_NE(nullptr, keyEvent);
10113 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10114 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10115 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10116 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010117 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10118 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010119 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10120 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010121 mWindow->assertNoEvents();
10122}
10123
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010124/**
10125 * Send an event to the app and have the app not respond right away.
10126 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10127 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10128 * At some point, the window becomes responsive again.
10129 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10130 */
10131TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10133 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10134 .build());
10135
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010136 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010137 ASSERT_TRUE(sequenceNum);
10138 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10139 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10140
10141 mWindow->finishEvent(*sequenceNum);
10142 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10143 ASSERT_TRUE(mDispatcher->waitForIdle());
10144 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10145
10146 // Now that the window is responsive, let's continue the gesture.
10147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10148 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10149 .build());
10150
10151 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10152 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10153 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10154 .build());
10155
10156 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10157 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10158 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10159 .build());
10160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10161 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10162 .build());
10163 // We already canceled this pointer, so the window shouldn't get any new events.
10164 mWindow->assertNoEvents();
10165
10166 // Start another one.
10167 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10168 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10169 .build());
10170 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10171}
10172
Prabir Pradhanfc364722024-02-08 17:51:20 +000010173// Send an event to the app and have the app not respond right away. Then remove the app window.
10174// When the window is removed, the dispatcher will cancel the events for that window.
10175// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10176TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10177 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010178 AINPUT_SOURCE_TOUCHSCREEN,
10179 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010180
10181 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10182 ASSERT_TRUE(sequenceNum);
10183
10184 // Remove the window, but the input channel should remain alive.
10185 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10186
10187 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10188 // Since the window was removed, Dispatcher does not know the PID associated with the window
10189 // anymore, so the policy is notified without the PID.
10190 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10191 /*pid=*/std::nullopt);
10192
10193 mWindow->finishEvent(*sequenceNum);
10194 // The cancellation was generated when the window was removed, along with the focus event.
10195 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010196 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010197 mWindow->consumeFocusEvent(false);
10198 ASSERT_TRUE(mDispatcher->waitForIdle());
10199 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10200}
10201
10202// Send an event to the app and have the app not respond right away. Wait for the policy to be
10203// notified of the unresponsive window, then remove the app window.
10204TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10205 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010206 AINPUT_SOURCE_TOUCHSCREEN,
10207 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010208
10209 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10210 ASSERT_TRUE(sequenceNum);
10211 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10212 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10213
10214 // Remove the window, but the input channel should remain alive.
10215 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10216
10217 mWindow->finishEvent(*sequenceNum);
10218 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10219 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010220 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010221 mWindow->consumeFocusEvent(false);
10222 ASSERT_TRUE(mDispatcher->waitForIdle());
10223 // Since the window was removed, Dispatcher does not know the PID associated with the window
10224 // becoming responsive, so the policy is notified without the PID.
10225 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10226}
10227
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010228class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10229 virtual void SetUp() override {
10230 InputDispatcherTest::SetUp();
10231
Chris Yea209fde2020-07-22 13:54:51 -070010232 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010233 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010234 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010235 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010236 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010237 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010238 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010239
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010240 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010241 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010242 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010243 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010244
10245 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010246 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010247 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010248
10249 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010250 mDispatcher->onWindowInfosChanged(
10251 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010252 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010253 mFocusedWindow->consumeFocusEvent(true);
10254 }
10255
10256 virtual void TearDown() override {
10257 InputDispatcherTest::TearDown();
10258
10259 mUnfocusedWindow.clear();
10260 mFocusedWindow.clear();
10261 }
10262
10263protected:
Chris Yea209fde2020-07-22 13:54:51 -070010264 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010265 sp<FakeWindowHandle> mUnfocusedWindow;
10266 sp<FakeWindowHandle> mFocusedWindow;
10267 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10268 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10269 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10270
10271 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10272
10273 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10274
10275private:
10276 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010278 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10279 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010281 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10282 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010283 }
10284};
10285
10286// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10287// should be ANR'd first.
10288TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010290 injectMotionEvent(*mDispatcher,
10291 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10292 AINPUT_SOURCE_TOUCHSCREEN)
10293 .pointer(PointerBuilder(0, ToolType::FINGER)
10294 .x(FOCUSED_WINDOW_LOCATION.x)
10295 .y(FOCUSED_WINDOW_LOCATION.y))
10296 .build()));
10297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10298 injectMotionEvent(*mDispatcher,
10299 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10300 AINPUT_SOURCE_TOUCHSCREEN)
10301 .pointer(PointerBuilder(0, ToolType::FINGER)
10302 .x(FOCUSED_WINDOW_LOCATION.x)
10303 .y(FOCUSED_WINDOW_LOCATION.y))
10304 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010305 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010306 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010307 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010308 // We consumed all events, so no ANR
10309 ASSERT_TRUE(mDispatcher->waitForIdle());
10310 mFakePolicy->assertNotifyAnrWasNotCalled();
10311
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010313 injectMotionEvent(*mDispatcher,
10314 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10315 AINPUT_SOURCE_TOUCHSCREEN)
10316 .pointer(PointerBuilder(0, ToolType::FINGER)
10317 .x(FOCUSED_WINDOW_LOCATION.x)
10318 .y(FOCUSED_WINDOW_LOCATION.y))
10319 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010320 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010321 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010322
10323 const std::chrono::duration timeout =
10324 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010325 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010326
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010327 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010328 mFocusedWindow->consumeMotionDown();
10329 // This cancel is generated because the connection was unresponsive
10330 mFocusedWindow->consumeMotionCancel();
10331 mFocusedWindow->assertNoEvents();
10332 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010333 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010334 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10335 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010336 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010337}
10338
10339// If we have 2 windows with identical timeouts that are both unresponsive,
10340// it doesn't matter which order they should have ANR.
10341// But we should receive ANR for both.
10342TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10343 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010344 mUnfocusedWindow->setDispatchingTimeout(
10345 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010346 mDispatcher->onWindowInfosChanged(
10347 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010348
10349 tapOnFocusedWindow();
10350 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010351 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010352 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10353 mFocusedWindow->getDispatchingTimeout(
10354 DISPATCHING_TIMEOUT)),
10355 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10356
10357 ASSERT_THAT(anrConnectionTokens,
10358 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10359 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010360
10361 ASSERT_TRUE(mDispatcher->waitForIdle());
10362 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010363
10364 mFocusedWindow->consumeMotionDown();
10365 mFocusedWindow->consumeMotionUp();
10366 mUnfocusedWindow->consumeMotionOutside();
10367
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010368 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10369 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010370
10371 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010372 ASSERT_THAT(responsiveTokens,
10373 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10374 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010375 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010376}
10377
10378// If a window is already not responding, the second tap on the same window should be ignored.
10379// We should also log an error to account for the dropped event (not tested here).
10380// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10381TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10382 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010383 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010384 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010385 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010386 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010387 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010388 ASSERT_TRUE(upEventSequenceNum);
10389 const std::chrono::duration timeout =
10390 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010391 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010392
10393 // Tap once again
10394 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010395 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010396 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10397 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010398 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010399 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010400 FOCUSED_WINDOW_LOCATION));
10401 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10402 // valid touch target
10403 mUnfocusedWindow->assertNoEvents();
10404
10405 // Consume the first tap
10406 mFocusedWindow->finishEvent(*downEventSequenceNum);
10407 mFocusedWindow->finishEvent(*upEventSequenceNum);
10408 ASSERT_TRUE(mDispatcher->waitForIdle());
10409 // The second tap did not go to the focused window
10410 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010411 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010412 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10413 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010414 mFakePolicy->assertNotifyAnrWasNotCalled();
10415}
10416
10417// If you tap outside of all windows, there will not be ANR
10418TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010419 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010420 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10421 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010422 ASSERT_TRUE(mDispatcher->waitForIdle());
10423 mFakePolicy->assertNotifyAnrWasNotCalled();
10424}
10425
10426// Since the focused window is paused, tapping on it should not produce any events
10427TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10428 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010429 mDispatcher->onWindowInfosChanged(
10430 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010431
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010432 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010433 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10434 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010435
10436 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10437 ASSERT_TRUE(mDispatcher->waitForIdle());
10438 // Should not ANR because the window is paused, and touches shouldn't go to it
10439 mFakePolicy->assertNotifyAnrWasNotCalled();
10440
10441 mFocusedWindow->assertNoEvents();
10442 mUnfocusedWindow->assertNoEvents();
10443}
10444
10445/**
10446 * 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 -070010447 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010448 * If a different window becomes focused at this time, the key should go to that window instead.
10449 *
10450 * Warning!!!
10451 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10452 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010453 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010454 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10455 *
10456 * If that value changes, this test should also change.
10457 */
10458TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10459 // Set a long ANR timeout to prevent it from triggering
10460 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010461 mDispatcher->onWindowInfosChanged(
10462 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010463
10464 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010465 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010466 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010467 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010468 ASSERT_TRUE(upSequenceNum);
10469 // Don't finish the events yet, and send a key
10470 // Injection will succeed because we will eventually give up and send the key to the focused
10471 // window even if motions are still being processed.
10472
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010473 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010474 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10475 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010476 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010478 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010479 // and the key remains pending, waiting for the touch events to be processed.
10480 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10481 // under the hood.
10482 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10483 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010484
10485 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010486 mFocusedWindow->setFocusable(false);
10487 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010488 mDispatcher->onWindowInfosChanged(
10489 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010490 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010491
10492 // Focus events should precede the key events
10493 mUnfocusedWindow->consumeFocusEvent(true);
10494 mFocusedWindow->consumeFocusEvent(false);
10495
10496 // Finish the tap events, which should unblock dispatcher
10497 mUnfocusedWindow->finishEvent(*downSequenceNum);
10498 mUnfocusedWindow->finishEvent(*upSequenceNum);
10499
10500 // Now that all queues are cleared and no backlog in the connections, the key event
10501 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010502 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010503 mFocusedWindow->assertNoEvents();
10504 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010505 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010506}
10507
10508// When the touch stream is split across 2 windows, and one of them does not respond,
10509// then ANR should be raised and the touch should be canceled for the unresponsive window.
10510// The other window should not be affected by that.
10511TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10512 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010513 mDispatcher->notifyMotion(
10514 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10515 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10516 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010517
10518 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010519 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010520 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10521 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010522 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010523
10524 const std::chrono::duration timeout =
10525 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010526 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010527
10528 mUnfocusedWindow->consumeMotionDown();
10529 mFocusedWindow->consumeMotionDown();
10530 // Focused window may or may not receive ACTION_MOVE
10531 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010532 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010533 ASSERT_TRUE(moveOrCancelSequenceNum);
10534 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10535 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010536 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010537 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10538 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10539 mFocusedWindow->consumeMotionCancel();
10540 } else {
10541 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10542 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010543 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010544 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10545 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010546
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010547 mUnfocusedWindow->assertNoEvents();
10548 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010549 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010550}
10551
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010552/**
10553 * If we have no focused window, and a key comes in, we start the ANR timer.
10554 * The focused application should add a focused window before the timer runs out to prevent ANR.
10555 *
10556 * If the user touches another application during this time, the key should be dropped.
10557 * Next, if a new focused window comes in, without toggling the focused application,
10558 * then no ANR should occur.
10559 *
10560 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10561 * but in some cases the policy may not update the focused application.
10562 */
10563TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10564 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10565 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010566 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010567 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010568 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10569 mFocusedWindow->setFocusable(false);
10570
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010571 mDispatcher->onWindowInfosChanged(
10572 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010573 mFocusedWindow->consumeFocusEvent(false);
10574
10575 // Send a key. The ANR timer should start because there is no focused window.
10576 // 'focusedApplication' will get blamed if this timer completes.
10577 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010578 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010579 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10580 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010581 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010582 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010584
10585 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10586 // then the injected touches won't cause the focused event to get dropped.
10587 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10588 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10589 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10590 // For this test, it means that the key would get delivered to the window once it becomes
10591 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010592 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010593
10594 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010595 mDispatcher->notifyMotion(
10596 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10597 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010598
10599 // We do not consume the motion right away, because that would require dispatcher to first
10600 // process (== drop) the key event, and by that time, ANR will be raised.
10601 // Set the focused window first.
10602 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010603 mDispatcher->onWindowInfosChanged(
10604 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010605 setFocusedWindow(mFocusedWindow);
10606 mFocusedWindow->consumeFocusEvent(true);
10607 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10608 // to another application. This could be a bug / behaviour in the policy.
10609
10610 mUnfocusedWindow->consumeMotionDown();
10611
10612 ASSERT_TRUE(mDispatcher->waitForIdle());
10613 // Should not ANR because we actually have a focused window. It was just added too slowly.
10614 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10615}
10616
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010617/**
10618 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10619 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10620 * dispatcher doesn't prune pointer events incorrectly.
10621 *
10622 * This test reproduces a crash in InputDispatcher.
10623 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10624 *
10625 * Keep the currently focused application (mApplication), and have no focused window.
10626 * We set up two additional windows:
10627 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10628 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10629 * window. This window is not focusable, but is touchable.
10630 *
10631 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10632 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10633 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10634 *
10635 * Now, we touch "Another window". This window is owned by a different application than
10636 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10637 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10638 * dropping the events from its queue. Ensure that no crash occurs.
10639 *
10640 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10641 * This does not affect the test running time.
10642 */
10643TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10644 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10645 std::make_shared<FakeApplicationHandle>();
10646 systemUiApplication->setDispatchingTimeout(3000ms);
10647 mFakePolicy->setStaleEventTimeout(3000ms);
10648 sp<FakeWindowHandle> navigationBar =
10649 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010650 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010651 navigationBar->setFocusable(false);
10652 navigationBar->setWatchOutsideTouch(true);
10653 navigationBar->setFrame(Rect(0, 0, 100, 100));
10654
10655 mApplication->setDispatchingTimeout(3000ms);
10656 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010657 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010658
10659 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10660 std::make_shared<FakeApplicationHandle>();
10661 sp<FakeWindowHandle> appWindow =
10662 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010663 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010664 appWindow->setFocusable(false);
10665 appWindow->setFrame(Rect(100, 100, 200, 200));
10666
10667 mDispatcher->onWindowInfosChanged(
10668 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10669 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10670 mFocusedWindow->consumeFocusEvent(false);
10671
10672 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10673 // in response.
10674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10675 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10676 .build());
10677 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10678
10679 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10680 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10681 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010682 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10683 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010684 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010685 /*allowKeyRepeat=*/false);
10686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10687
10688 // Finish the gesture - lift up finger and inject ACTION_UP key event
10689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10690 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10691 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010692 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10693 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010694 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010695 /*allowKeyRepeat=*/false);
10696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10697 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10698 // getting any events yet.
10699 navigationBar->assertNoEvents();
10700
10701 // Now touch "Another window". This touch is going to a different application than the one we
10702 // are waiting for (which is 'mApplication').
10703 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
10704 // trying to be injected) and to continue processing the rest of the events in the original
10705 // order.
10706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10707 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10708 .build());
10709 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
10710 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
10711 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10712
10713 appWindow->assertNoEvents();
10714 navigationBar->assertNoEvents();
10715}
10716
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010717// These tests ensure we cannot send touch events to a window that's positioned behind a window
10718// that has feature NO_INPUT_CHANNEL.
10719// Layout:
10720// Top (closest to user)
10721// mNoInputWindow (above all windows)
10722// mBottomWindow
10723// Bottom (furthest from user)
10724class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
10725 virtual void SetUp() override {
10726 InputDispatcherTest::SetUp();
10727
10728 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010729 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10730 "Window without input channel",
10731 ui::LogicalDisplayId::DEFAULT,
10732 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010733 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010734 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
10735 // It's perfectly valid for this window to not have an associated input channel
10736
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010737 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010738 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010739 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
10740
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010741 mDispatcher->onWindowInfosChanged(
10742 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010743 }
10744
10745protected:
10746 std::shared_ptr<FakeApplicationHandle> mApplication;
10747 sp<FakeWindowHandle> mNoInputWindow;
10748 sp<FakeWindowHandle> mBottomWindow;
10749};
10750
10751TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
10752 PointF touchedPoint = {10, 10};
10753
Prabir Pradhan678438e2023-04-13 19:32:51 +000010754 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010755 AINPUT_SOURCE_TOUCHSCREEN,
10756 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010757
10758 mNoInputWindow->assertNoEvents();
10759 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
10760 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
10761 // and therefore should prevent mBottomWindow from receiving touches
10762 mBottomWindow->assertNoEvents();
10763}
10764
10765/**
10766 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
10767 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
10768 */
10769TEST_F(InputDispatcherMultiWindowOcclusionTests,
10770 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010771 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10772 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010773 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010774
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010775 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010776 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010777 mDispatcher->onWindowInfosChanged(
10778 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010779
10780 PointF touchedPoint = {10, 10};
10781
Prabir Pradhan678438e2023-04-13 19:32:51 +000010782 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010783 AINPUT_SOURCE_TOUCHSCREEN,
10784 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010785
10786 mNoInputWindow->assertNoEvents();
10787 mBottomWindow->assertNoEvents();
10788}
10789
Vishnu Nair958da932020-08-21 17:12:37 -070010790class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
10791protected:
10792 std::shared_ptr<FakeApplicationHandle> mApp;
10793 sp<FakeWindowHandle> mWindow;
10794 sp<FakeWindowHandle> mMirror;
10795
10796 virtual void SetUp() override {
10797 InputDispatcherTest::SetUp();
10798 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010799 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10800 ui::LogicalDisplayId::DEFAULT);
10801 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
10802 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070010803 mWindow->setFocusable(true);
10804 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010805 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010806 }
10807};
10808
10809TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
10810 // Request focus on a mirrored window
10811 setFocusedWindow(mMirror);
10812
10813 // window gets focused
10814 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010816 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010817 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010818}
10819
10820// A focused & mirrored window remains focused only if the window and its mirror are both
10821// focusable.
10822TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
10823 setFocusedWindow(mMirror);
10824
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010825 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070010826 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010828 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010829 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010831 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010832 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010833
10834 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010835 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010836
10837 // window loses focus since one of the windows associated with the token in not focusable
10838 mWindow->consumeFocusEvent(false);
10839
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010840 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010841 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010842 mWindow->assertNoEvents();
10843}
10844
10845// A focused & mirrored window remains focused until the window and its mirror both become
10846// invisible.
10847TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
10848 setFocusedWindow(mMirror);
10849
10850 // window gets focused
10851 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010853 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010854 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010856 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010857 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010858
10859 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010860 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010861
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010863 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010864 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010866 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010867 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010868
10869 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010870 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010871
10872 // window loses focus only after all windows associated with the token become invisible.
10873 mWindow->consumeFocusEvent(false);
10874
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010875 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010876 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010877 mWindow->assertNoEvents();
10878}
10879
10880// A focused & mirrored window remains focused until both windows are removed.
10881TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
10882 setFocusedWindow(mMirror);
10883
10884 // window gets focused
10885 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010887 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010888 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010890 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010891 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010892
10893 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010894 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010895
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010897 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010898 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010900 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010901 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010902
10903 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010904 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010905 mWindow->consumeFocusEvent(false);
10906
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010907 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010908 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010909 mWindow->assertNoEvents();
10910}
10911
10912// Focus request can be pending until one window becomes visible.
10913TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
10914 // Request focus on an invisible mirror.
10915 mWindow->setVisible(false);
10916 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010917 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010918 setFocusedWindow(mMirror);
10919
10920 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010922 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010923 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070010924
10925 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010926 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010927
10928 // window gets focused
10929 mWindow->consumeFocusEvent(true);
10930 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010931 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070010932}
Prabir Pradhan99987712020-11-10 18:43:05 -080010933
10934class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
10935protected:
10936 std::shared_ptr<FakeApplicationHandle> mApp;
10937 sp<FakeWindowHandle> mWindow;
10938 sp<FakeWindowHandle> mSecondWindow;
10939
10940 void SetUp() override {
10941 InputDispatcherTest::SetUp();
10942 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010943 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10944 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010945 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010946 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
10947 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010948 mSecondWindow->setFocusable(true);
10949
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010950 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010951 mDispatcher->onWindowInfosChanged(
10952 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080010953
10954 setFocusedWindow(mWindow);
10955 mWindow->consumeFocusEvent(true);
10956 }
10957
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010958 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010959 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080010960 }
10961
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010962 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
10963 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080010964 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090010965 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010966 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010967 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010968 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080010969 }
10970};
10971
10972TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
10973 // Ensure that capture cannot be obtained for unfocused windows.
10974 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
10975 mFakePolicy->assertSetPointerCaptureNotCalled();
10976 mSecondWindow->assertNoEvents();
10977
10978 // Ensure that capture can be enabled from the focus window.
10979 requestAndVerifyPointerCapture(mWindow, true);
10980
10981 // Ensure that capture cannot be disabled from a window that does not have capture.
10982 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
10983 mFakePolicy->assertSetPointerCaptureNotCalled();
10984
10985 // Ensure that capture can be disabled from the window with capture.
10986 requestAndVerifyPointerCapture(mWindow, false);
10987}
10988
10989TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010990 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010991
10992 setFocusedWindow(mSecondWindow);
10993
10994 // Ensure that the capture disabled event was sent first.
10995 mWindow->consumeCaptureEvent(false);
10996 mWindow->consumeFocusEvent(false);
10997 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090010998 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010999
11000 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011001 notifyPointerCaptureChanged({});
11002 notifyPointerCaptureChanged(request);
11003 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011004 mWindow->assertNoEvents();
11005 mSecondWindow->assertNoEvents();
11006 mFakePolicy->assertSetPointerCaptureNotCalled();
11007}
11008
11009TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011010 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011011
11012 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011013 notifyPointerCaptureChanged({});
11014 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011015
11016 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011017 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011018 mWindow->consumeCaptureEvent(false);
11019 mWindow->assertNoEvents();
11020}
11021
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011022TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11023 requestAndVerifyPointerCapture(mWindow, true);
11024
11025 // The first window loses focus.
11026 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011027 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011028 mWindow->consumeCaptureEvent(false);
11029
11030 // Request Pointer Capture from the second window before the notification from InputReader
11031 // arrives.
11032 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011033 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011034
11035 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011036 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011037
11038 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011039 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011040
11041 mSecondWindow->consumeFocusEvent(true);
11042 mSecondWindow->consumeCaptureEvent(true);
11043}
11044
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011045TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11046 // App repeatedly enables and disables capture.
11047 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011048 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011049 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011050 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011051 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011052 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011053
11054 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11055 // first request is now stale, this should do nothing.
11056 notifyPointerCaptureChanged(firstRequest);
11057 mWindow->assertNoEvents();
11058
11059 // InputReader notifies that the second request was enabled.
11060 notifyPointerCaptureChanged(secondRequest);
11061 mWindow->consumeCaptureEvent(true);
11062}
11063
Prabir Pradhan7092e262022-05-03 16:51:09 +000011064TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11065 requestAndVerifyPointerCapture(mWindow, true);
11066
11067 // App toggles pointer capture off and on.
11068 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011069 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011070
11071 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011072 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011073
11074 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11075 // preceding "disable" request.
11076 notifyPointerCaptureChanged(enableRequest);
11077
11078 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11079 // any notifications.
11080 mWindow->assertNoEvents();
11081}
11082
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011083/**
11084 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11085 * mouse movements don't affect the previous mouse hovering state.
11086 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11087 * HOVER_MOVE events).
11088 */
11089TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11090 // Mouse hover on the window
11091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11092 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11093 .build());
11094 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11095 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11096 .build());
11097
11098 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11099 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11100
11101 // Start pointer capture
11102 requestAndVerifyPointerCapture(mWindow, true);
11103
11104 // Send some relative mouse movements and receive them in the window.
11105 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11106 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11107 .build());
11108 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11109 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11110
11111 // Stop pointer capture
11112 requestAndVerifyPointerCapture(mWindow, false);
11113
11114 // Continue hovering on the window
11115 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11116 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11117 .build());
11118 mWindow->consumeMotionEvent(
11119 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11120
11121 mWindow->assertNoEvents();
11122}
11123
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011124TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11125 // The default display is the focused display to begin with.
11126 requestAndVerifyPointerCapture(mWindow, true);
11127
11128 // Move the second window to a second display, make it the focused window on that display.
11129 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11130 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11131 setFocusedWindow(mSecondWindow);
11132 mSecondWindow->consumeFocusEvent(true);
11133
11134 mWindow->assertNoEvents();
11135
11136 // The second window cannot gain capture because it is not on the focused display.
11137 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11138 mFakePolicy->assertSetPointerCaptureNotCalled();
11139 mSecondWindow->assertNoEvents();
11140
11141 // Make the second display the focused display.
11142 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011143 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011144
11145 // This causes the first window to lose pointer capture, and it's unable to request capture.
11146 mWindow->consumeCaptureEvent(false);
11147 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11148
11149 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11150 mFakePolicy->assertSetPointerCaptureNotCalled();
11151
11152 // The second window is now able to gain pointer capture successfully.
11153 requestAndVerifyPointerCapture(mSecondWindow, true);
11154}
11155
Hiroki Sato25040232024-02-22 17:21:22 +090011156using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11157
11158TEST_F(InputDispatcherPointerCaptureDeathTest,
11159 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11160 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11161 ScopedSilentDeath _silentDeath;
11162
11163 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11164 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11165
11166 // Dispatch a pointer changed event with a wrong token.
11167 request.window = mSecondWindow->getToken();
11168 ASSERT_DEATH(
11169 {
11170 notifyPointerCaptureChanged(request);
11171 mSecondWindow->consumeCaptureEvent(true);
11172 },
11173 "Unexpected requested window for Pointer Capture.");
11174}
11175
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011176class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11177protected:
11178 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011179
11180 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11181 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11182
11183 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11184 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11185
11186 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11187 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11188 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11189 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11190 MAXIMUM_OBSCURING_OPACITY);
11191
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011192 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11193 static constexpr gui::Uid APP_B_UID{10002};
11194 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011195
11196 sp<FakeWindowHandle> mTouchWindow;
11197
11198 virtual void SetUp() override {
11199 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011200 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011201 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11202 }
11203
11204 virtual void TearDown() override {
11205 InputDispatcherTest::TearDown();
11206 mTouchWindow.clear();
11207 }
11208
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011209 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011210 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011211 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011212 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011213 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011214 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011215 return window;
11216 }
11217
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011218 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011219 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11220 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011221 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011222 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011223 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011224 return window;
11225 }
11226
11227 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011228 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011229 AINPUT_SOURCE_TOUCHSCREEN,
11230 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011231 }
11232};
11233
11234TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011235 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011236 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011237 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011238
11239 touch();
11240
11241 mTouchWindow->assertNoEvents();
11242}
11243
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011244TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011245 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11246 const sp<FakeWindowHandle>& w =
11247 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011248 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011249
11250 touch();
11251
11252 mTouchWindow->assertNoEvents();
11253}
11254
11255TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011256 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11257 const sp<FakeWindowHandle>& w =
11258 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011259 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011260
11261 touch();
11262
11263 w->assertNoEvents();
11264}
11265
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011266TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011267 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011268 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011269
11270 touch();
11271
11272 mTouchWindow->consumeAnyMotionDown();
11273}
11274
11275TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011276 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011277 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011278 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011279 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011280
11281 touch({PointF{100, 100}});
11282
11283 mTouchWindow->consumeAnyMotionDown();
11284}
11285
11286TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011287 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011288 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011289 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011290
11291 touch();
11292
11293 mTouchWindow->consumeAnyMotionDown();
11294}
11295
11296TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11297 const sp<FakeWindowHandle>& w =
11298 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011299 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011300
11301 touch();
11302
11303 mTouchWindow->consumeAnyMotionDown();
11304}
11305
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011306TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11307 const sp<FakeWindowHandle>& w =
11308 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011309 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011310
11311 touch();
11312
11313 w->assertNoEvents();
11314}
11315
11316/**
11317 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11318 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11319 * window, the occluding window will still receive ACTION_OUTSIDE event.
11320 */
11321TEST_F(InputDispatcherUntrustedTouchesTest,
11322 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11323 const sp<FakeWindowHandle>& w =
11324 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011325 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011326 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011327
11328 touch();
11329
11330 w->consumeMotionOutside();
11331}
11332
11333TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11334 const sp<FakeWindowHandle>& w =
11335 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011336 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011337 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011338
11339 touch();
11340
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011341 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011342}
11343
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011344TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011345 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011346 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11347 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011348 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011349
11350 touch();
11351
11352 mTouchWindow->consumeAnyMotionDown();
11353}
11354
11355TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11356 const sp<FakeWindowHandle>& w =
11357 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11358 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011359 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011360
11361 touch();
11362
11363 mTouchWindow->consumeAnyMotionDown();
11364}
11365
11366TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011367 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011368 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11369 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011370 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011371
11372 touch();
11373
11374 mTouchWindow->assertNoEvents();
11375}
11376
11377TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11378 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11379 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011380 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11381 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011382 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011383 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11384 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011385 mDispatcher->onWindowInfosChanged(
11386 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011387
11388 touch();
11389
11390 mTouchWindow->assertNoEvents();
11391}
11392
11393TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11394 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11395 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011396 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11397 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011398 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011399 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11400 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011401 mDispatcher->onWindowInfosChanged(
11402 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011403
11404 touch();
11405
11406 mTouchWindow->consumeAnyMotionDown();
11407}
11408
11409TEST_F(InputDispatcherUntrustedTouchesTest,
11410 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11411 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011412 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11413 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011414 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011415 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11416 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011417 mDispatcher->onWindowInfosChanged(
11418 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011419
11420 touch();
11421
11422 mTouchWindow->consumeAnyMotionDown();
11423}
11424
11425TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11426 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011427 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11428 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011429 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011430 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11431 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011432 mDispatcher->onWindowInfosChanged(
11433 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011434
11435 touch();
11436
11437 mTouchWindow->assertNoEvents();
11438}
11439
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011440TEST_F(InputDispatcherUntrustedTouchesTest,
11441 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11442 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011443 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11444 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011445 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011446 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11447 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011448 mDispatcher->onWindowInfosChanged(
11449 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011450
11451 touch();
11452
11453 mTouchWindow->assertNoEvents();
11454}
11455
11456TEST_F(InputDispatcherUntrustedTouchesTest,
11457 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11458 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011459 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11460 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011461 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011462 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11463 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011464 mDispatcher->onWindowInfosChanged(
11465 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011466
11467 touch();
11468
11469 mTouchWindow->consumeAnyMotionDown();
11470}
11471
11472TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11473 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011474 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11475 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011476 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011477
11478 touch();
11479
11480 mTouchWindow->consumeAnyMotionDown();
11481}
11482
11483TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11484 const sp<FakeWindowHandle>& w =
11485 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011486 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011487
11488 touch();
11489
11490 mTouchWindow->consumeAnyMotionDown();
11491}
11492
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011493TEST_F(InputDispatcherUntrustedTouchesTest,
11494 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11495 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11496 const sp<FakeWindowHandle>& w =
11497 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011498 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011499
11500 touch();
11501
11502 mTouchWindow->assertNoEvents();
11503}
11504
11505TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11506 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11507 const sp<FakeWindowHandle>& w =
11508 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011509 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011510
11511 touch();
11512
11513 mTouchWindow->consumeAnyMotionDown();
11514}
11515
11516TEST_F(InputDispatcherUntrustedTouchesTest,
11517 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11518 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11519 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011520 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11521 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011522 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011523
11524 touch();
11525
11526 mTouchWindow->consumeAnyMotionDown();
11527}
11528
11529TEST_F(InputDispatcherUntrustedTouchesTest,
11530 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11531 const sp<FakeWindowHandle>& w1 =
11532 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11533 OPACITY_BELOW_THRESHOLD);
11534 const sp<FakeWindowHandle>& w2 =
11535 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11536 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011537 mDispatcher->onWindowInfosChanged(
11538 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011539
11540 touch();
11541
11542 mTouchWindow->assertNoEvents();
11543}
11544
11545/**
11546 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11547 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11548 * (which alone would result in allowing touches) does not affect the blocking behavior.
11549 */
11550TEST_F(InputDispatcherUntrustedTouchesTest,
11551 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11552 const sp<FakeWindowHandle>& wB =
11553 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11554 OPACITY_BELOW_THRESHOLD);
11555 const sp<FakeWindowHandle>& wC =
11556 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11557 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011558 mDispatcher->onWindowInfosChanged(
11559 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011560
11561 touch();
11562
11563 mTouchWindow->assertNoEvents();
11564}
11565
11566/**
11567 * This test is testing that a window from a different UID but with same application token doesn't
11568 * block the touch. Apps can share the application token for close UI collaboration for example.
11569 */
11570TEST_F(InputDispatcherUntrustedTouchesTest,
11571 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11572 const sp<FakeWindowHandle>& w =
11573 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11574 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011575 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011576
11577 touch();
11578
11579 mTouchWindow->consumeAnyMotionDown();
11580}
11581
arthurhungb89ccb02020-12-30 16:19:01 +080011582class InputDispatcherDragTests : public InputDispatcherTest {
11583protected:
11584 std::shared_ptr<FakeApplicationHandle> mApp;
11585 sp<FakeWindowHandle> mWindow;
11586 sp<FakeWindowHandle> mSecondWindow;
11587 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011588 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011589 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11590 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011591
11592 void SetUp() override {
11593 InputDispatcherTest::SetUp();
11594 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011595 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11596 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011597 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011598
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011599 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11600 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011601 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011602
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011603 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11604 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011605 mSpyWindow->setSpy(true);
11606 mSpyWindow->setTrustedOverlay(true);
11607 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11608
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011609 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011610 mDispatcher->onWindowInfosChanged(
11611 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11612 {},
11613 0,
11614 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011615 }
11616
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011617 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11618 switch (fromSource) {
11619 case AINPUT_SOURCE_TOUCHSCREEN:
11620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011621 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011622 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11624 break;
11625 case AINPUT_SOURCE_STYLUS:
11626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011627 injectMotionEvent(*mDispatcher,
11628 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11629 AINPUT_SOURCE_STYLUS)
11630 .buttonState(
11631 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11632 .pointer(PointerBuilder(0, ToolType::STYLUS)
11633 .x(50)
11634 .y(50))
11635 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011636 break;
11637 case AINPUT_SOURCE_MOUSE:
11638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011639 injectMotionEvent(*mDispatcher,
11640 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11641 AINPUT_SOURCE_MOUSE)
11642 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11643 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11644 ToolType::MOUSE)
11645 .x(50)
11646 .y(50))
11647 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011648 break;
11649 default:
11650 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11651 }
arthurhungb89ccb02020-12-30 16:19:01 +080011652
11653 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011654 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011655 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011656 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011657 }
11658
11659 // Start performing drag, we will create a drag window and transfer touch to it.
11660 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11661 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011662 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011663 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011664 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011665 }
arthurhungb89ccb02020-12-30 16:19:01 +080011666
11667 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011668 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11669 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011670 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011671 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11672 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11673 {},
11674 0,
11675 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011676
11677 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011678 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011679 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11680 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011681 if (transferred) {
11682 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011683 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11684 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011685 }
11686 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011687 }
11688};
11689
11690TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011691 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011692
11693 // Move on window.
11694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011695 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011696 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011698 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11699 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011700 mWindow->consumeDragEvent(false, 50, 50);
11701 mSecondWindow->assertNoEvents();
11702
11703 // Move to another window.
11704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011705 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011706 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011708 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11709 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011710 mWindow->consumeDragEvent(true, 150, 50);
11711 mSecondWindow->consumeDragEvent(false, 50, 50);
11712
11713 // Move back to original window.
11714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011715 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011716 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011718 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11719 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011720 mWindow->consumeDragEvent(false, 50, 50);
11721 mSecondWindow->consumeDragEvent(true, -50, 50);
11722
11723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011724 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011725 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011727 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011728 mWindow->assertNoEvents();
11729 mSecondWindow->assertNoEvents();
11730}
11731
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011732TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011733 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011734
11735 // No cancel event after drag start
11736 mSpyWindow->assertNoEvents();
11737
11738 const MotionEvent secondFingerDownEvent =
11739 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11740 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011741 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11742 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011743 .build();
11744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011745 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011746 InputEventInjectionSync::WAIT_FOR_RESULT))
11747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11748
11749 // Receives cancel for first pointer after next pointer down
11750 mSpyWindow->consumeMotionCancel();
11751 mSpyWindow->consumeMotionDown();
11752
11753 mSpyWindow->assertNoEvents();
11754}
11755
arthurhungf452d0b2021-01-06 00:19:52 +080011756TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011757 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080011758
11759 // Move on window.
11760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011761 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011762 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011764 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11765 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011766 mWindow->consumeDragEvent(false, 50, 50);
11767 mSecondWindow->assertNoEvents();
11768
11769 // Move to another window.
11770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011771 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011772 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011774 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11775 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011776 mWindow->consumeDragEvent(true, 150, 50);
11777 mSecondWindow->consumeDragEvent(false, 50, 50);
11778
11779 // drop to another window.
11780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011781 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080011782 {150, 50}))
11783 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011784 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011785 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080011786 mWindow->assertNoEvents();
11787 mSecondWindow->assertNoEvents();
11788}
11789
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011790TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
11791 startDrag();
11792
11793 // No cancel event after drag start
11794 mSpyWindow->assertNoEvents();
11795
11796 const MotionEvent secondFingerDownEvent =
11797 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11798 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11799 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11800 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11801 .build();
11802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11803 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11804 InputEventInjectionSync::WAIT_FOR_RESULT))
11805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11806
11807 // Receives cancel for first pointer after next pointer down
11808 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080011809 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011810 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
11811
11812 mSpyWindow->assertNoEvents();
11813
11814 // Spy window calls pilfer pointers
11815 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
11816 mDragWindow->assertNoEvents();
11817
11818 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011819 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011820 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11821 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
11822 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11823 .build();
11824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011825 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011826 InputEventInjectionSync::WAIT_FOR_RESULT))
11827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11828
11829 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000011830 mDragWindow->consumeMotionEvent(
11831 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011832 mDragWindow->assertNoEvents();
11833}
11834
arthurhung6d4bed92021-03-17 11:59:33 +080011835TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011836 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080011837
11838 // Move on window and keep button pressed.
11839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011840 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011841 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11842 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011843 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011844 .build()))
11845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011846 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11847 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011848 mWindow->consumeDragEvent(false, 50, 50);
11849 mSecondWindow->assertNoEvents();
11850
11851 // Move to another window and release button, expect to drop item.
11852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011853 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011854 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11855 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011856 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011857 .build()))
11858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011859 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11860 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011861 mWindow->assertNoEvents();
11862 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011863 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080011864
11865 // nothing to the window.
11866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011867 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011868 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
11869 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011870 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011871 .build()))
11872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011873 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011874 mWindow->assertNoEvents();
11875 mSecondWindow->assertNoEvents();
11876}
11877
Arthur Hung54745652022-04-20 07:17:41 +000011878TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011879 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080011880
11881 // Set second window invisible.
11882 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011883 mDispatcher->onWindowInfosChanged(
11884 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080011885
11886 // Move on window.
11887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011888 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011889 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011891 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11892 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011893 mWindow->consumeDragEvent(false, 50, 50);
11894 mSecondWindow->assertNoEvents();
11895
11896 // Move to another window.
11897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011898 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011899 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011901 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11902 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011903 mWindow->consumeDragEvent(true, 150, 50);
11904 mSecondWindow->assertNoEvents();
11905
11906 // drop to another window.
11907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011908 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080011909 {150, 50}))
11910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011911 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011912 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011913 mWindow->assertNoEvents();
11914 mSecondWindow->assertNoEvents();
11915}
11916
Arthur Hung54745652022-04-20 07:17:41 +000011917TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011918 // Ensure window could track pointerIds if it didn't support split touch.
11919 mWindow->setPreventSplitting(true);
11920
Arthur Hung54745652022-04-20 07:17:41 +000011921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011922 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11923 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011925 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011926
11927 const MotionEvent secondFingerDownEvent =
11928 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011929 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011933 .build();
11934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011935 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011936 InputEventInjectionSync::WAIT_FOR_RESULT))
11937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011938 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000011939
11940 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011941 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011942}
11943
11944TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
11945 // First down on second window.
11946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011947 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11948 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11950
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011951 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011952
11953 // Second down on first window.
11954 const MotionEvent secondFingerDownEvent =
11955 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011956 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011957 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011958 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11959 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011960 .build();
11961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011962 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011963 InputEventInjectionSync::WAIT_FOR_RESULT))
11964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011965 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
11966 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011967
11968 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011969 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011970
11971 // Move on window.
11972 const MotionEvent secondFingerMoveEvent =
11973 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11974 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011975 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11976 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011977 .build();
11978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011979 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011980 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011981 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11982 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011983 mWindow->consumeDragEvent(false, 50, 50);
11984 mSecondWindow->consumeMotionMove();
11985
11986 // Release the drag pointer should perform drop.
11987 const MotionEvent secondFingerUpEvent =
11988 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11989 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011990 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11991 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011992 .build();
11993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011994 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011995 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011996 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011997 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000011998 mWindow->assertNoEvents();
11999 mSecondWindow->consumeMotionMove();
12000}
12001
Arthur Hung3915c1f2022-05-31 07:17:17 +000012002TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012003 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012004
12005 // Update window of second display.
12006 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012007 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012008 mDispatcher->onWindowInfosChanged(
12009 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12010 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12011 {},
12012 0,
12013 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012014
12015 // Let second display has a touch state.
12016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012017 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012018 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12019 AINPUT_SOURCE_TOUCHSCREEN)
12020 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012021 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012022 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012023 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012024 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012025 mDispatcher->onWindowInfosChanged(
12026 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12027 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12028 {},
12029 0,
12030 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012031
12032 // Move on window.
12033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012034 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012035 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012037 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12038 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012039 mWindow->consumeDragEvent(false, 50, 50);
12040 mSecondWindow->assertNoEvents();
12041
12042 // Move to another window.
12043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012044 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012045 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012047 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12048 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012049 mWindow->consumeDragEvent(true, 150, 50);
12050 mSecondWindow->consumeDragEvent(false, 50, 50);
12051
12052 // drop to another window.
12053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012054 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012055 {150, 50}))
12056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012057 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012058 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012059 mWindow->assertNoEvents();
12060 mSecondWindow->assertNoEvents();
12061}
12062
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012063TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12064 startDrag(true, AINPUT_SOURCE_MOUSE);
12065 // Move on window.
12066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012067 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012068 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12069 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012070 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012071 .x(50)
12072 .y(50))
12073 .build()))
12074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012075 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12076 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012077 mWindow->consumeDragEvent(false, 50, 50);
12078 mSecondWindow->assertNoEvents();
12079
12080 // Move to another window.
12081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012082 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012083 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12084 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012085 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012086 .x(150)
12087 .y(50))
12088 .build()))
12089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012090 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12091 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012092 mWindow->consumeDragEvent(true, 150, 50);
12093 mSecondWindow->consumeDragEvent(false, 50, 50);
12094
12095 // drop to another window.
12096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012097 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012098 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12099 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012100 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012101 .x(150)
12102 .y(50))
12103 .build()))
12104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012105 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012106 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012107 mWindow->assertNoEvents();
12108 mSecondWindow->assertNoEvents();
12109}
12110
Linnan Li5af92f92023-07-14 14:36:22 +080012111/**
12112 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12113 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12114 */
12115TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12116 // Down on second window
12117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12119 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12121
12122 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12123 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12124
12125 // Down on first window
12126 const MotionEvent secondFingerDownEvent =
12127 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012128 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012129 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12130 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12131 .build();
12132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12133 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12134 InputEventInjectionSync::WAIT_FOR_RESULT))
12135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12136 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12137 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12138 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12139
12140 // Start drag on first window
12141 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12142
12143 // Trigger cancel
12144 mDispatcher->cancelCurrentTouch();
12145 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012146 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012147 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012148 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12149
12150 ASSERT_TRUE(mDispatcher->waitForIdle());
12151 // The D&D finished with nullptr
12152 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12153
12154 // Remove drag window
12155 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12156
12157 // Inject a simple gesture, ensure dispatcher not crashed
12158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012159 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12160 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12162 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12163
12164 const MotionEvent moveEvent =
12165 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012166 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012167 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12168 .build();
12169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12170 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12171 InputEventInjectionSync::WAIT_FOR_RESULT))
12172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12173 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12174
12175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012176 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012177 {50, 50}))
12178 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12179 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12180}
12181
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012182TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12183 // Start hovering over the window.
12184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12185 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012186 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012187
12188 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12189 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12190
12191 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12192 << "Drag and drop should not work with a hovering pointer";
12193}
12194
Linnan Lia512a532024-10-08 16:19:16 +080012195/**
12196 * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if
12197 * we perform a click using Device B, the dispatcher should work well.
12198 */
12199TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) {
12200 const DeviceId deviceA = 1;
12201 const DeviceId deviceB = 2;
12202 // First down on second window with deviceA.
12203 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12204 .deviceId(deviceA)
12205 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12206 .build());
12207 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12208 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12209
12210 // Second down on first window with deviceA
12211 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12212 .deviceId(deviceA)
12213 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12214 .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50))
12215 .build());
12216 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12217 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12218 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12219 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12220
12221 // Perform drag and drop from first window.
12222 ASSERT_TRUE(startDrag(/*sendDown=*/false));
12223
12224 // Click first window with device B, we should ensure dispatcher work well.
12225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
12226 .deviceId(deviceB)
12227 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12228 .build());
12229 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
12230 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12231
12232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
12233 .deviceId(deviceB)
12234 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12235 .build());
12236 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB),
12237 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12238
12239 // Move with device A.
12240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12241 .deviceId(deviceA)
12242 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12243 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12244 .build());
12245
12246 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12247 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12248 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12249 mWindow->consumeDragEvent(false, 51, 51);
12250 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12251 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12252
12253 // Releasing the drag pointer should cause drop.
12254 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12255 .deviceId(deviceA)
12256 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12257 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12258 .build());
12259 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
12260 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12261 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12262 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
12263 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12264 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12265
12266 // Release all pointers.
12267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12268 .deviceId(deviceA)
12269 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12270 .build());
12271 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
12272 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12273 mWindow->assertNoEvents();
12274}
12275
Vishnu Nair062a8672021-09-03 16:07:44 -070012276class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12277
12278TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012280 sp<FakeWindowHandle> window =
12281 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12282 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012283 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012284 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012285 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012286 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012287 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012288 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012289
12290 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012291 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012292 window->assertNoEvents();
12293
Prabir Pradhan678438e2023-04-13 19:32:51 +000012294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012295 AINPUT_SOURCE_TOUCHSCREEN,
12296 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012297 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012298 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012299 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012300 window->assertNoEvents();
12301
12302 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012303 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012304 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012305
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012306 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12307 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012308
Prabir Pradhan678438e2023-04-13 19:32:51 +000012309 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012310 AINPUT_SOURCE_TOUCHSCREEN,
12311 ui::LogicalDisplayId::DEFAULT));
12312 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012313 window->assertNoEvents();
12314}
12315
12316TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12317 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12318 std::make_shared<FakeApplicationHandle>();
12319 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012320 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012321 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012322 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012323 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012324 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012326 sp<FakeWindowHandle> window =
12327 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12328 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012329 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012330 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012331 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012332 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012333 mDispatcher->onWindowInfosChanged(
12334 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012335 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012336 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012337
12338 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012339 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012340 window->assertNoEvents();
12341
Prabir Pradhan678438e2023-04-13 19:32:51 +000012342 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012343 AINPUT_SOURCE_TOUCHSCREEN,
12344 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012345 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012346 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012347 window->assertNoEvents();
12348
12349 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012350 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012351 mDispatcher->onWindowInfosChanged(
12352 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012353
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012354 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12355 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012356
Prabir Pradhan678438e2023-04-13 19:32:51 +000012357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012358 AINPUT_SOURCE_TOUCHSCREEN,
12359 ui::LogicalDisplayId::DEFAULT));
12360 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12361 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012362 window->assertNoEvents();
12363}
12364
12365TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12366 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12367 std::make_shared<FakeApplicationHandle>();
12368 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012369 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012370 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012371 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012372 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012373 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012375 sp<FakeWindowHandle> window =
12376 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12377 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012378 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012379 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012380 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012381 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012382 mDispatcher->onWindowInfosChanged(
12383 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012384 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012385 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012386
12387 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012388 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012389 window->assertNoEvents();
12390
Prabir Pradhan678438e2023-04-13 19:32:51 +000012391 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012392 AINPUT_SOURCE_TOUCHSCREEN,
12393 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012394 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012395 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012396 window->assertNoEvents();
12397
12398 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012399 mDispatcher->onWindowInfosChanged(
12400 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012401
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012402 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12403 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012404
Prabir Pradhan678438e2023-04-13 19:32:51 +000012405 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012406 AINPUT_SOURCE_TOUCHSCREEN,
12407 ui::LogicalDisplayId::DEFAULT));
12408 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012409 window->assertNoEvents();
12410}
12411
Antonio Kantekf16f2832021-09-28 04:39:20 +000012412class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12413protected:
12414 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012415 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012416 sp<FakeWindowHandle> mWindow;
12417 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012418 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012419
12420 void SetUp() override {
12421 InputDispatcherTest::SetUp();
12422
12423 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012424 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012425 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12426 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012427 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012428 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012429 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12430 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012431 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012432 mThirdWindow =
12433 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12434 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12435 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012436
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012437 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012438 mDispatcher->onWindowInfosChanged(
12439 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12440 {},
12441 0,
12442 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012443 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012444 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012445
Antonio Kantek15beb512022-06-13 22:35:41 +000012446 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012447 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012448 WINDOW_UID, /*hasPermission=*/true,
12449 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012450 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12451 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012452 mThirdWindow->assertNoEvents();
12453 }
12454
12455 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12456 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012457 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012458 SECOND_DISPLAY_ID)) {
12459 mWindow->assertNoEvents();
12460 mSecondWindow->assertNoEvents();
12461 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012462 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012463 }
12464
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012465 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012466 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012467 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012468 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012469 mWindow->consumeTouchModeEvent(inTouchMode);
12470 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012471 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012472 }
12473};
12474
Antonio Kantek26defcf2022-02-08 01:12:27 +000012475TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012476 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012477 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12478 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012479 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012480}
12481
Antonio Kantek26defcf2022-02-08 01:12:27 +000012482TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12483 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012484 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012485 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012486 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012487 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012488 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012489 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012490 mWindow->assertNoEvents();
12491 mSecondWindow->assertNoEvents();
12492}
12493
12494TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12495 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012496 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012497 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012498 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012499 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012500 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012501}
12502
Antonio Kantekf16f2832021-09-28 04:39:20 +000012503TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012504 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012505 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12506 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012507 /*hasPermission=*/true,
12508 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012509 mWindow->assertNoEvents();
12510 mSecondWindow->assertNoEvents();
12511}
12512
Antonio Kantek15beb512022-06-13 22:35:41 +000012513TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12514 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12515 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12516 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012517 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012518 mWindow->assertNoEvents();
12519 mSecondWindow->assertNoEvents();
12520 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12521}
12522
Antonio Kantek48710e42022-03-24 14:19:30 -070012523TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12524 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012526 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012527 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012528 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012529
12530 // Then remove focus.
12531 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012532 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012533
12534 // Assert that caller can switch touch mode by owning one of the last interacted window.
12535 const WindowInfo& windowInfo = *mWindow->getInfo();
12536 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12537 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012538 /*hasPermission=*/false,
12539 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012540}
12541
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012542class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12543public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012544 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012545 std::shared_ptr<FakeApplicationHandle> application =
12546 std::make_shared<FakeApplicationHandle>();
12547 std::string name = "Fake Spy ";
12548 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012549 sp<FakeWindowHandle> spy =
12550 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12551 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012552 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012553 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012554 return spy;
12555 }
12556
12557 sp<FakeWindowHandle> createForeground() {
12558 std::shared_ptr<FakeApplicationHandle> application =
12559 std::make_shared<FakeApplicationHandle>();
12560 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012561 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012562 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012563 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012564 return window;
12565 }
12566
12567private:
12568 int mSpyCount{0};
12569};
12570
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012571using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012572/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012573 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12574 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012575TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012576 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012577 ScopedSilentDeath _silentDeath;
12578
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012579 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012580 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012581 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012582 ".* not a trusted overlay");
12583}
12584
12585/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012586 * Input injection into a display with a spy window but no foreground windows should succeed.
12587 */
12588TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012589 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012590 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012591
12592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012593 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12594 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012596 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012597}
12598
12599/**
12600 * Verify the order in which different input windows receive events. The touched foreground window
12601 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12602 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12603 * receive events before ones belows it.
12604 *
12605 * Here, we set up a scenario with four windows in the following Z order from the top:
12606 * spy1, spy2, window, spy3.
12607 * We then inject an event and verify that the foreground "window" receives it first, followed by
12608 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12609 * window.
12610 */
12611TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12612 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012613 auto spy1 = createSpy();
12614 auto spy2 = createSpy();
12615 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012616 mDispatcher->onWindowInfosChanged(
12617 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012618 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12619 const size_t numChannels = channels.size();
12620
Michael Wright8e9a8562022-02-09 13:44:29 +000012621 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012622 if (!epollFd.ok()) {
12623 FAIL() << "Failed to create epoll fd";
12624 }
12625
12626 for (size_t i = 0; i < numChannels; i++) {
12627 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12628 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12629 FAIL() << "Failed to add fd to epoll";
12630 }
12631 }
12632
12633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012634 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12635 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12637
12638 std::vector<size_t> eventOrder;
12639 std::vector<struct epoll_event> events(numChannels);
12640 for (;;) {
12641 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12642 (100ms).count());
12643 if (nFds < 0) {
12644 FAIL() << "Failed to call epoll_wait";
12645 }
12646 if (nFds == 0) {
12647 break; // epoll_wait timed out
12648 }
12649 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012650 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012651 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012652 channels[i]->consumeMotionDown();
12653 }
12654 }
12655
12656 // Verify the order in which the events were received.
12657 EXPECT_EQ(3u, eventOrder.size());
12658 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12659 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12660 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12661}
12662
12663/**
12664 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12665 */
12666TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12667 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012668 auto spy = createSpy();
12669 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012670 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012671
12672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012673 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12674 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012676 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012677 spy->assertNoEvents();
12678}
12679
12680/**
12681 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12682 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12683 * to the window.
12684 */
12685TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12686 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012687 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012688 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012689 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012690
12691 // Inject an event outside the spy window's touchable region.
12692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012693 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12694 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12696 window->consumeMotionDown();
12697 spy->assertNoEvents();
12698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012699 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12700 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12702 window->consumeMotionUp();
12703 spy->assertNoEvents();
12704
12705 // Inject an event inside the spy window's touchable region.
12706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012707 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12708 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12710 window->consumeMotionDown();
12711 spy->consumeMotionDown();
12712}
12713
12714/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012715 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012716 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012717 */
12718TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12719 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012720 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012721 auto spy = createSpy();
12722 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012723 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012724 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012725 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012726
12727 // Inject an event outside the spy window's frame and touchable region.
12728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012729 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12730 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12732 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012733 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012734}
12735
12736/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012737 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12738 * pointers that are down within its bounds.
12739 */
12740TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12741 auto windowLeft = createForeground();
12742 windowLeft->setFrame({0, 0, 100, 200});
12743 auto windowRight = createForeground();
12744 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012745 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012746 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012747 mDispatcher->onWindowInfosChanged(
12748 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012749
12750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012751 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12752 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12754 windowLeft->consumeMotionDown();
12755 spy->consumeMotionDown();
12756
12757 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012758 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012759 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012760 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12761 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012762 .build();
12763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012764 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012765 InputEventInjectionSync::WAIT_FOR_RESULT))
12766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12767 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012768 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012769}
12770
12771/**
12772 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12773 * the spy should receive the second pointer with ACTION_DOWN.
12774 */
12775TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12776 auto window = createForeground();
12777 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012778 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012779 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012780 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012781
12782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012783 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12784 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012785 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12786 window->consumeMotionDown();
12787 spyRight->assertNoEvents();
12788
12789 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012790 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012791 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012792 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12793 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012794 .build();
12795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012796 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012797 InputEventInjectionSync::WAIT_FOR_RESULT))
12798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012799 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012800 spyRight->consumeMotionDown();
12801}
12802
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012803/**
12804 * The spy window should not be able to affect whether or not touches are split. Only the foreground
12805 * windows should be allowed to control split touch.
12806 */
12807TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012808 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012809 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012810 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012811 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012812
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012813 auto window = createForeground();
12814 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012815
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012816 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012817
12818 // First finger down, no window touched.
12819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012820 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12821 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012823 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012824 window->assertNoEvents();
12825
12826 // Second finger down on window, the window should receive touch down.
12827 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012828 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012829 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012830 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012831 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12832 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012833 .build();
12834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012835 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012836 InputEventInjectionSync::WAIT_FOR_RESULT))
12837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12838
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012839 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000012840 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012841}
12842
12843/**
12844 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
12845 * do not receive key events.
12846 */
12847TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012848 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012849 spy->setFocusable(false);
12850
12851 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012852 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012853 setFocusedWindow(window);
12854 window->consumeFocusEvent(true);
12855
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012857 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012858 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012859
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012861 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012862 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012863
12864 spy->assertNoEvents();
12865}
12866
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012867using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
12868
12869/**
12870 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
12871 * are currently sent to any other windows - including other spy windows - will also be cancelled.
12872 */
12873TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
12874 auto window = createForeground();
12875 auto spy1 = createSpy();
12876 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012877 mDispatcher->onWindowInfosChanged(
12878 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012879
12880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012881 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12882 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12884 window->consumeMotionDown();
12885 spy1->consumeMotionDown();
12886 spy2->consumeMotionDown();
12887
12888 // Pilfer pointers from the second spy window.
12889 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
12890 spy2->assertNoEvents();
12891 spy1->consumeMotionCancel();
12892 window->consumeMotionCancel();
12893
12894 // The rest of the gesture should only be sent to the second spy window.
12895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012896 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012897 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12899 spy2->consumeMotionMove();
12900 spy1->assertNoEvents();
12901 window->assertNoEvents();
12902}
12903
12904/**
12905 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
12906 * in the middle of the gesture.
12907 */
12908TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
12909 auto window = createForeground();
12910 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012911 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012912
12913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012914 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12915 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012917 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12918 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012919
12920 window->releaseChannel();
12921
12922 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12923
12924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012925 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12926 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012928 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012929}
12930
12931/**
12932 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
12933 * the spy, but not to any other windows.
12934 */
12935TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
12936 auto spy = createSpy();
12937 auto window = createForeground();
12938
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012939 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012940
12941 // First finger down on the window and the spy.
12942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012943 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12944 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12946 spy->consumeMotionDown();
12947 window->consumeMotionDown();
12948
12949 // Spy window pilfers the pointers.
12950 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12951 window->consumeMotionCancel();
12952
12953 // Second finger down on the window and spy, but the window should not receive the pointer down.
12954 const MotionEvent secondFingerDownEvent =
12955 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012956 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012957 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012958 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12959 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012960 .build();
12961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012962 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012963 InputEventInjectionSync::WAIT_FOR_RESULT))
12964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12965
Harry Cutts33476232023-01-30 19:57:29 +000012966 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012967
12968 // Third finger goes down outside all windows, so injection should fail.
12969 const MotionEvent thirdFingerDownEvent =
12970 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012971 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012972 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012973 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12974 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12975 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012976 .build();
12977 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012978 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012979 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080012980 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012981
12982 spy->assertNoEvents();
12983 window->assertNoEvents();
12984}
12985
12986/**
12987 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
12988 */
12989TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
12990 auto spy = createSpy();
12991 spy->setFrame(Rect(0, 0, 100, 100));
12992 auto window = createForeground();
12993 window->setFrame(Rect(0, 0, 200, 200));
12994
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012995 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012996
12997 // First finger down on the window only
12998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012999 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13000 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13002 window->consumeMotionDown();
13003
13004 // Second finger down on the spy and window
13005 const MotionEvent secondFingerDownEvent =
13006 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013007 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013008 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013009 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13010 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013011 .build();
13012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013013 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013014 InputEventInjectionSync::WAIT_FOR_RESULT))
13015 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13016 spy->consumeMotionDown();
13017 window->consumeMotionPointerDown(1);
13018
13019 // Third finger down on the spy and window
13020 const MotionEvent thirdFingerDownEvent =
13021 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013022 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013023 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013024 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13025 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13026 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013027 .build();
13028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013029 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013030 InputEventInjectionSync::WAIT_FOR_RESULT))
13031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13032 spy->consumeMotionPointerDown(1);
13033 window->consumeMotionPointerDown(2);
13034
13035 // Spy window pilfers the pointers.
13036 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013037 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13038 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13039 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13040 WithPointerCount(3)));
13041 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13042 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13043 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13044 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013045
13046 spy->assertNoEvents();
13047 window->assertNoEvents();
13048}
13049
13050/**
13051 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13052 * other windows should be canceled. If this results in the cancellation of all pointers for some
13053 * window, then that window should receive ACTION_CANCEL.
13054 */
13055TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13056 auto spy = createSpy();
13057 spy->setFrame(Rect(0, 0, 100, 100));
13058 auto window = createForeground();
13059 window->setFrame(Rect(0, 0, 200, 200));
13060
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013061 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013062
13063 // First finger down on both spy and window
13064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013065 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13066 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13068 window->consumeMotionDown();
13069 spy->consumeMotionDown();
13070
13071 // Second finger down on the spy and window
13072 const MotionEvent secondFingerDownEvent =
13073 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013074 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013075 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013076 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13077 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013078 .build();
13079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013080 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013081 InputEventInjectionSync::WAIT_FOR_RESULT))
13082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13083 spy->consumeMotionPointerDown(1);
13084 window->consumeMotionPointerDown(1);
13085
13086 // Spy window pilfers the pointers.
13087 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13088 window->consumeMotionCancel();
13089
13090 spy->assertNoEvents();
13091 window->assertNoEvents();
13092}
13093
13094/**
13095 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13096 * be sent to other windows
13097 */
13098TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13099 auto spy = createSpy();
13100 spy->setFrame(Rect(0, 0, 100, 100));
13101 auto window = createForeground();
13102 window->setFrame(Rect(0, 0, 200, 200));
13103
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013104 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013105
13106 // First finger down on both window and spy
13107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013108 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13109 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13111 window->consumeMotionDown();
13112 spy->consumeMotionDown();
13113
13114 // Spy window pilfers the pointers.
13115 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13116 window->consumeMotionCancel();
13117
13118 // Second finger down on the window only
13119 const MotionEvent secondFingerDownEvent =
13120 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013121 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013122 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013123 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13124 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013125 .build();
13126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013127 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013128 InputEventInjectionSync::WAIT_FOR_RESULT))
13129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13130 window->consumeMotionDown();
13131 window->assertNoEvents();
13132
13133 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13134 spy->consumeMotionMove();
13135 spy->assertNoEvents();
13136}
13137
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013138/**
13139 * A window on the left and a window on the right. Also, a spy window that's above all of the
13140 * windows, and spanning both left and right windows.
13141 * Send simultaneous motion streams from two different devices, one to the left window, and another
13142 * to the right window.
13143 * Pilfer from spy window.
13144 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13145 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013146TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13147 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013148 sp<FakeWindowHandle> spy = createSpy();
13149 spy->setFrame(Rect(0, 0, 200, 200));
13150 sp<FakeWindowHandle> leftWindow = createForeground();
13151 leftWindow->setFrame(Rect(0, 0, 100, 100));
13152
13153 sp<FakeWindowHandle> rightWindow = createForeground();
13154 rightWindow->setFrame(Rect(100, 0, 200, 100));
13155
13156 constexpr int32_t stylusDeviceId = 1;
13157 constexpr int32_t touchDeviceId = 2;
13158
13159 mDispatcher->onWindowInfosChanged(
13160 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13161
13162 // Stylus down on left window and spy
13163 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13164 .deviceId(stylusDeviceId)
13165 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13166 .build());
13167 leftWindow->consumeMotionEvent(
13168 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13169 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13170
13171 // Finger down on right window and spy - but spy already has stylus
13172 mDispatcher->notifyMotion(
13173 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13174 .deviceId(touchDeviceId)
13175 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13176 .build());
13177 rightWindow->consumeMotionEvent(
13178 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013179 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013180
13181 // Act: pilfer from spy. Spy is currently receiving touch events.
13182 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013183 leftWindow->consumeMotionEvent(
13184 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013185 rightWindow->consumeMotionEvent(
13186 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13187
13188 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13189 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13190 .deviceId(stylusDeviceId)
13191 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13192 .build());
13193 mDispatcher->notifyMotion(
13194 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13195 .deviceId(touchDeviceId)
13196 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13197 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013198 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013199
13200 spy->assertNoEvents();
13201 leftWindow->assertNoEvents();
13202 rightWindow->assertNoEvents();
13203}
13204
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013205/**
13206 * A window on the left and a window on the right. Also, a spy window that's above all of the
13207 * windows, and spanning both left and right windows.
13208 * Send simultaneous motion streams from two different devices, one to the left window, and another
13209 * to the right window.
13210 * Pilfer from spy window.
13211 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13212 * The spy should receive both the touch and the stylus events after pilfer.
13213 */
13214TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13215 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13216 sp<FakeWindowHandle> spy = createSpy();
13217 spy->setFrame(Rect(0, 0, 200, 200));
13218 sp<FakeWindowHandle> leftWindow = createForeground();
13219 leftWindow->setFrame(Rect(0, 0, 100, 100));
13220
13221 sp<FakeWindowHandle> rightWindow = createForeground();
13222 rightWindow->setFrame(Rect(100, 0, 200, 100));
13223
13224 constexpr int32_t stylusDeviceId = 1;
13225 constexpr int32_t touchDeviceId = 2;
13226
13227 mDispatcher->onWindowInfosChanged(
13228 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13229
13230 // Stylus down on left window and spy
13231 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13232 .deviceId(stylusDeviceId)
13233 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13234 .build());
13235 leftWindow->consumeMotionEvent(
13236 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13237 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13238
13239 // Finger down on right window and spy
13240 mDispatcher->notifyMotion(
13241 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13242 .deviceId(touchDeviceId)
13243 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13244 .build());
13245 rightWindow->consumeMotionEvent(
13246 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13247 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13248
13249 // Act: pilfer from spy. Spy is currently receiving touch events.
13250 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13251 leftWindow->consumeMotionEvent(
13252 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13253 rightWindow->consumeMotionEvent(
13254 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13255
13256 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013257 // Instead of sending the two MOVE events for each input device together, and then receiving
13258 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13259 // means that the two MOVE events will be initially put into a batch. Once the events are
13260 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13261 // on the implementation of InputConsumer), which would mean that the order of the received
13262 // events could be different depending on whether there are 1 or 2 events pending in the
13263 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13264 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013265 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13266 .deviceId(stylusDeviceId)
13267 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13268 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013269 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013270 mDispatcher->notifyMotion(
13271 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13272 .deviceId(touchDeviceId)
13273 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13274 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013275 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013276
13277 spy->assertNoEvents();
13278 leftWindow->assertNoEvents();
13279 rightWindow->assertNoEvents();
13280}
13281
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013282TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13283 auto window = createForeground();
13284 auto spy = createSpy();
13285 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13286
13287 mDispatcher->notifyMotion(
13288 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13289 .deviceId(1)
13290 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13291 .build());
13292 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13293 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13294
13295 // Pilfer pointers from the spy window should fail.
13296 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13297 spy->assertNoEvents();
13298 window->assertNoEvents();
13299}
13300
Prabir Pradhand65552b2021-10-07 11:23:50 -070013301class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13302public:
13303 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13304 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13305 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013306 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13307 "Stylus interceptor window",
13308 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013309 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013310 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013311 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013312 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013313 overlay->setTrustedOverlay(true);
13314
13315 std::shared_ptr<FakeApplicationHandle> application =
13316 std::make_shared<FakeApplicationHandle>();
13317 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013318 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013319 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013320 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013321 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013322
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013323 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013324 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013325 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013326 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013327 return {std::move(overlay), std::move(window)};
13328 }
13329
13330 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013331 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013332 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013333 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013334 }
13335
13336 void sendStylusEvent(int32_t action) {
13337 NotifyMotionArgs motionArgs =
13338 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013339 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013340 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013341 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013342 }
13343};
13344
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013345using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13346
13347TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013348 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013349 ScopedSilentDeath _silentDeath;
13350
Prabir Pradhand65552b2021-10-07 11:23:50 -070013351 auto [overlay, window] = setupStylusOverlayScenario();
13352 overlay->setTrustedOverlay(false);
13353 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013354 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13355 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013356 ".* not a trusted overlay");
13357}
13358
13359TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13360 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013361 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013362
13363 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13364 overlay->consumeMotionDown();
13365 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13366 overlay->consumeMotionUp();
13367
13368 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13369 window->consumeMotionDown();
13370 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13371 window->consumeMotionUp();
13372
13373 overlay->assertNoEvents();
13374 window->assertNoEvents();
13375}
13376
13377TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13378 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013379 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013380 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013381
13382 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13383 overlay->consumeMotionDown();
13384 window->consumeMotionDown();
13385 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13386 overlay->consumeMotionUp();
13387 window->consumeMotionUp();
13388
13389 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13390 window->consumeMotionDown();
13391 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13392 window->consumeMotionUp();
13393
13394 overlay->assertNoEvents();
13395 window->assertNoEvents();
13396}
13397
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013398/**
13399 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13400 * The scenario is as follows:
13401 * - The stylus interceptor overlay is configured as a spy window.
13402 * - The stylus interceptor spy receives the start of a new stylus gesture.
13403 * - It pilfers pointers and then configures itself to no longer be a spy.
13404 * - The stylus interceptor continues to receive the rest of the gesture.
13405 */
13406TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13407 auto [overlay, window] = setupStylusOverlayScenario();
13408 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013409 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013410
13411 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13412 overlay->consumeMotionDown();
13413 window->consumeMotionDown();
13414
13415 // The interceptor pilfers the pointers.
13416 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13417 window->consumeMotionCancel();
13418
13419 // The interceptor configures itself so that it is no longer a spy.
13420 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013421 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013422
13423 // It continues to receive the rest of the stylus gesture.
13424 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13425 overlay->consumeMotionMove();
13426 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13427 overlay->consumeMotionUp();
13428
13429 window->assertNoEvents();
13430}
13431
Prabir Pradhan5735a322022-04-11 17:23:34 +000013432struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013433 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013434 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013435 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13436 std::unique_ptr<InputDispatcher>& mDispatcher;
13437
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013438 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013439 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13440
13441 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013442 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013443 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013444 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13445 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13446 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13447 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13448 }
13449
13450 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013451 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013452 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013453 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013454 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013455 mPolicyFlags);
13456 }
13457
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013458 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013459 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13460 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013461 sp<FakeWindowHandle> window =
13462 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13463 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013464 window->setOwnerInfo(mPid, mUid);
13465 return window;
13466 }
13467};
13468
13469using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13470
13471TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013472 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013473 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013474 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013475
13476 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13477 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13478 window->consumeMotionDown();
13479
13480 setFocusedWindow(window);
13481 window->consumeFocusEvent(true);
13482
13483 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13484 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013485 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013486}
13487
13488TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013489 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013490 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013491 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013492
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013493 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013494 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13495 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13496
13497 setFocusedWindow(window);
13498 window->consumeFocusEvent(true);
13499
13500 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13501 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13502 window->assertNoEvents();
13503}
13504
13505TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013506 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013507 auto window = owner.createWindow("Owned window");
13508 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013509 spy->setSpy(true);
13510 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013511 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013512
13513 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13514 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13515 spy->consumeMotionDown();
13516 window->consumeMotionDown();
13517}
13518
13519TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013520 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013521 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013522
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013523 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013524 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013525 randosSpy->setSpy(true);
13526 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013527 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013528
13529 // The event is targeted at owner's window, so injection should succeed, but the spy should
13530 // not receive the event.
13531 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13532 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13533 randosSpy->assertNoEvents();
13534 window->consumeMotionDown();
13535}
13536
13537TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013538 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013539 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013540
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013541 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013542 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013543 randosSpy->setSpy(true);
13544 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013545 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013546
13547 // A user that has injection permission can inject into any window.
13548 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013549 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013550 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013551 randosSpy->consumeMotionDown();
13552 window->consumeMotionDown();
13553
13554 setFocusedWindow(randosSpy);
13555 randosSpy->consumeFocusEvent(true);
13556
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013557 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013558 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013559 window->assertNoEvents();
13560}
13561
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013562TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013563 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013564 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013565
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013566 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013567 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013568 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13569 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013570 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013571
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013572 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013573 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13574 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13575 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013576 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013577}
13578
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013579using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13580
13581TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13583
13584 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013585 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013586 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013587 sp<FakeWindowHandle> right =
13588 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13589 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013590 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013591 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13592 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013593 spy->setFrame(Rect(0, 0, 200, 100));
13594 spy->setTrustedOverlay(true);
13595 spy->setSpy(true);
13596
13597 mDispatcher->onWindowInfosChanged(
13598 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13599
13600 // Hover into the left window.
13601 mDispatcher->notifyMotion(
13602 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13603 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13604 .build());
13605
13606 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13607 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13608
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013609 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13610 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013611 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013612 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13613 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013614 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013615 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13616 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013617 /*pointerId=*/0));
13618
13619 // Hover move to the right window.
13620 mDispatcher->notifyMotion(
13621 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13622 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13623 .build());
13624
13625 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13626 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13627 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13628
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013629 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13630 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013631 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013632 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13633 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013634 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013635 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13636 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013637 /*pointerId=*/0));
13638
13639 // Stop hovering.
13640 mDispatcher->notifyMotion(
13641 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13642 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13643 .build());
13644
13645 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13646 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13647
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013648 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13649 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013650 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013651 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13652 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013653 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013654 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13655 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013656 /*pointerId=*/0));
13657}
13658
13659TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13661
13662 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013663 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013664 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013665 sp<FakeWindowHandle> right =
13666 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13667 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013668 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013669 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13670 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013671 spy->setFrame(Rect(0, 0, 200, 100));
13672 spy->setTrustedOverlay(true);
13673 spy->setSpy(true);
13674
13675 mDispatcher->onWindowInfosChanged(
13676 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13677
13678 // First pointer down on left window.
13679 mDispatcher->notifyMotion(
13680 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13681 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13682 .build());
13683
13684 left->consumeMotionDown();
13685 spy->consumeMotionDown();
13686
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013687 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13688 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013689 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013690 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13691 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013692 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013693 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13694 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013695 /*pointerId=*/0));
13696
13697 // Second pointer down on right window.
13698 mDispatcher->notifyMotion(
13699 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13700 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13701 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13702 .build());
13703
13704 left->consumeMotionMove();
13705 right->consumeMotionDown();
13706 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13707
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013708 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13709 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013710 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013711 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13712 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013713 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013714 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13715 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013716 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013717 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13718 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013719 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013720 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13721 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013722 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013723 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13724 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013725 /*pointerId=*/1));
13726
13727 // Second pointer up.
13728 mDispatcher->notifyMotion(
13729 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13730 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13731 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13732 .build());
13733
13734 left->consumeMotionMove();
13735 right->consumeMotionUp();
13736 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13737
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013738 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13739 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013740 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013741 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13742 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013743 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013744 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13745 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013746 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013747 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13748 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013749 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013750 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13751 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013752 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013753 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13754 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013755 /*pointerId=*/1));
13756
13757 // First pointer up.
13758 mDispatcher->notifyMotion(
13759 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13760 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13761 .build());
13762
13763 left->consumeMotionUp();
13764 spy->consumeMotionUp();
13765
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013766 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13767 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013768 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013769 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13770 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013771 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013772 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13773 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013774 /*pointerId=*/0));
13775}
13776
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013777TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13778 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013779 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13780
13781 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013782 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013783 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013784 sp<FakeWindowHandle> right =
13785 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13786 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013787 right->setFrame(Rect(100, 0, 200, 100));
13788
13789 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13790
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013791 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13792 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013793 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013794 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13795 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013796 /*pointerId=*/0));
13797
13798 // Hover move into the window.
13799 mDispatcher->notifyMotion(
13800 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13801 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13802 .rawXCursorPosition(50)
13803 .rawYCursorPosition(50)
13804 .deviceId(DEVICE_ID)
13805 .build());
13806
13807 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13808
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013809 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13810 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013811 /*pointerId=*/0));
13812
13813 // Move the mouse with another device. This cancels the hovering pointer from the first device.
13814 mDispatcher->notifyMotion(
13815 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13816 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13817 .rawXCursorPosition(51)
13818 .rawYCursorPosition(50)
13819 .deviceId(SECOND_DEVICE_ID)
13820 .build());
13821
13822 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13823 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13824
13825 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13826 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013827 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13828 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013829 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013830 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013831 SECOND_DEVICE_ID,
13832 /*pointerId=*/0));
13833
13834 // Move the mouse outside the window. Document the current behavior, where the window does not
13835 // receive HOVER_EXIT even though the mouse left the window.
13836 mDispatcher->notifyMotion(
13837 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13838 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13839 .rawXCursorPosition(150)
13840 .rawYCursorPosition(50)
13841 .deviceId(SECOND_DEVICE_ID)
13842 .build());
13843
13844 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13845 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013846 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13847 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013848 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013849 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013850 SECOND_DEVICE_ID,
13851 /*pointerId=*/0));
13852}
13853
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013854/**
13855 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
13856 * the same cursor, and therefore have a shared motion event stream.
13857 */
13858TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
13859 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13861
13862 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013863 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013864 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013865 sp<FakeWindowHandle> right =
13866 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13867 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013868 right->setFrame(Rect(100, 0, 200, 100));
13869
13870 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13871
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013872 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13873 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013874 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013875 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13876 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013877 /*pointerId=*/0));
13878
13879 // Hover move into the window.
13880 mDispatcher->notifyMotion(
13881 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13882 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13883 .rawXCursorPosition(50)
13884 .rawYCursorPosition(50)
13885 .deviceId(DEVICE_ID)
13886 .build());
13887
13888 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13889
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013890 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13891 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013892 /*pointerId=*/0));
13893
13894 // Move the mouse with another device
13895 mDispatcher->notifyMotion(
13896 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13897 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13898 .rawXCursorPosition(51)
13899 .rawYCursorPosition(50)
13900 .deviceId(SECOND_DEVICE_ID)
13901 .build());
13902 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13903
13904 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13905 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013906 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13907 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013908 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013909 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013910 SECOND_DEVICE_ID,
13911 /*pointerId=*/0));
13912
13913 // Move the mouse outside the window. Document the current behavior, where the window does not
13914 // receive HOVER_EXIT even though the mouse left the window.
13915 mDispatcher->notifyMotion(
13916 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13917 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13918 .rawXCursorPosition(150)
13919 .rawYCursorPosition(50)
13920 .deviceId(SECOND_DEVICE_ID)
13921 .build());
13922
13923 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013924 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13925 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013926 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013927 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013928 SECOND_DEVICE_ID,
13929 /*pointerId=*/0));
13930}
13931
Arpit Singhb65e2bd2024-06-03 09:48:16 +000013932TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
13933 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
13934 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
13935}
13936
Garfield Tane84e6f92019-08-29 17:28:41 -070013937} // namespace android::inputdispatcher