blob: 3413caa1f05e1daaa77b29ef54f089552adc79bc [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 -0800414TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000415 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
416 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000417 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000418 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800419
420 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
421 args.policyFlags |= POLICY_FLAG_TRUSTED;
422 mFakePolicy->assertNotifySwitchWasCalled(args);
423}
424
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700425namespace {
426
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700427static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700428
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000429class FakeMonitorReceiver {
430public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800431 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
432 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700433 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000434
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700435 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000436
Linnan Li13bf76a2024-05-05 19:18:02 +0800437 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700438 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
439 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000440 }
441
442 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800443 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
444 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000445 }
446
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700447 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000448
Linnan Li13bf76a2024-05-05 19:18:02 +0800449 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700450 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
451 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000452 }
453
Linnan Li13bf76a2024-05-05 19:18:02 +0800454 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700455 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
456 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000457 }
458
Linnan Li13bf76a2024-05-05 19:18:02 +0800459 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
461 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000462 }
463
Linnan Li13bf76a2024-05-05 19:18:02 +0800464 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000466 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
467 WithDisplayId(expectedDisplayId),
468 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
469 }
470
471 void consumeMotionPointerDown(int32_t pointerIdx) {
472 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
473 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700474 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700475 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000476 }
477
478 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700479 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000480 }
481
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800482 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000483
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800484 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000485
486private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700487 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000488};
489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800490static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700491 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700492 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800493 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800494 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000495 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000496 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800497 KeyEvent event;
498 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
499
500 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800501 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000502 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
503 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800504
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800505 if (!allowKeyRepeat) {
506 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
507 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800508 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700509 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800510}
511
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700512static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
513 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700514 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
515 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
516 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700517 if (result != InputEventInjectionResult::TIMED_OUT) {
518 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
519 }
520}
521
Linnan Li13bf76a2024-05-05 19:18:02 +0800522static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700523 InputDispatcher& dispatcher,
524 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000525 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700526}
527
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800528// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
529// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
530// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800531static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700532 InputDispatcher& dispatcher,
533 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000534 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800535 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000536 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800537}
538
Linnan Li13bf76a2024-05-05 19:18:02 +0800539static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700540 InputDispatcher& dispatcher,
541 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000542 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700543}
544
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800545static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700546 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700547 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000548 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000549 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700550 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
551 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700552}
553
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800554static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800555 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700556 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700557 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700558 AMOTION_EVENT_INVALID_CURSOR_POSITION},
559 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800560 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000561 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000562 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700563 MotionEventBuilder motionBuilder =
564 MotionEventBuilder(action, source)
565 .displayId(displayId)
566 .eventTime(eventTime)
567 .rawXCursorPosition(cursorPosition.x)
568 .rawYCursorPosition(cursorPosition.y)
569 .pointer(
570 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
571 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
572 motionBuilder.downTime(eventTime);
573 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800574
575 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700576 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
577 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800578}
579
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700580static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800581 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700582 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700583 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700584}
585
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700586static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800587 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800588 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700589 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000590}
591
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700592static NotifyKeyArgs generateKeyArgs(
593 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800594 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
595 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000596 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
597 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
598 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800599
600 return args;
601}
602
Prabir Pradhan678438e2023-04-13 19:32:51 +0000603[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800604 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000605 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800606 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700607 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
608 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
609 }
610
chaviwd1c23182019-12-20 18:44:56 -0800611 PointerProperties pointerProperties[pointerCount];
612 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800613
chaviwd1c23182019-12-20 18:44:56 -0800614 for (size_t i = 0; i < pointerCount; i++) {
615 pointerProperties[i].clear();
616 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700617 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800618
chaviwd1c23182019-12-20 18:44:56 -0800619 pointerCoords[i].clear();
620 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
621 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
622 }
Jackal Guof9696682018-10-05 12:23:23 +0800623
624 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
625 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000626 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
627 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
628 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800629 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000630 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700631 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000632 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800633
634 return args;
635}
636
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800637static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
638 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
639}
640
Linnan Li13bf76a2024-05-05 19:18:02 +0800641static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
642 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800643 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
644}
645
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000646static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
647 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000648 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
649 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800650}
651
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700652} // namespace
653
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800654/**
655 * When a window unexpectedly disposes of its input channel, policy should be notified about the
656 * broken channel.
657 */
658TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
661 "Window that breaks its input channel",
662 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800663
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700664 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800665
666 // Window closes its channel, but the window remains.
667 window->destroyReceiver();
668 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
669}
670
Arthur Hungb92218b2018-08-14 12:00:21 +0800671TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700673 sp<FakeWindowHandle> window =
674 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
675 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800676
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700679 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
680 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800682
683 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700684 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800685}
686
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800687using InputDispatcherDeathTest = InputDispatcherTest;
688
689/**
690 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
691 * should crash.
692 */
693TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
694 testing::GTEST_FLAG(death_test_style) = "threadsafe";
695 ScopedSilentDeath _silentDeath;
696
697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700698 sp<FakeWindowHandle> window =
699 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
700 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800701 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
702 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
703 "Incorrect WindowInfosUpdate provided");
704}
705
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700706TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
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);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700711
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700713 // Inject a MotionEvent to an unknown display.
714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
716 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
718
719 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700720 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700721}
722
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700723/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700724 * Calling onWindowInfosChanged once should not cause any issues.
725 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700726 * called twice.
727 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800728TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700730 sp<FakeWindowHandle> window =
731 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
732 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700733 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700734
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700735 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
738 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700740
741 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700742 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700743}
744
745/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700746 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700747 */
748TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700750 sp<FakeWindowHandle> window =
751 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
752 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700753 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
756 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
759 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700761
762 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700763 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700764}
765
Arthur Hungb92218b2018-08-14 12:00:21 +0800766// The foreground window should receive the first touch down event.
767TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700769 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
770 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000771 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700772 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
773 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700775 mDispatcher->onWindowInfosChanged(
776 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
779 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800781
782 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700783 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800784 windowSecond->assertNoEvents();
785}
786
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000787/**
788 * Two windows: A top window, and a wallpaper behind the window.
789 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
790 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800791 * 1. foregroundWindow <-- dup touch to wallpaper
792 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000793 */
794TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
796 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700797 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
798 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800799 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000800 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700801 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
802 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800803 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000804
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700805 mDispatcher->onWindowInfosChanged(
806 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800808 injectMotionEvent(*mDispatcher,
809 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
810 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
811 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
813
814 // Both foreground window and its wallpaper should receive the touch down
815 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700816 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000817
818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800819 injectMotionEvent(*mDispatcher,
820 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
821 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
822 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
824
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800825 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700826 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000827
828 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700829 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000830 foregroundWindow->consumeMotionCancel();
831 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700832 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000833}
834
835/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800836 * Two fingers down on the window, and lift off the first finger.
837 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
838 * contains a single pointer.
839 */
840TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
843 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800844
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700845 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
848 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
849 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800850 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000851 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
852 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
853 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
854 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800855 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000856 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
857 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
858 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
859 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800860 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
861 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
862 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
863
864 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700865 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800866 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
867 window->consumeMotionEvent(
868 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
869}
870
871/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800872 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
873 * with the following differences:
874 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
875 * clean up the connection.
876 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
877 * Ensure that there's no crash in the dispatcher.
878 */
879TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
881 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700882 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
883 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800884 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800885 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700886 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
887 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800888 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800889
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700890 mDispatcher->onWindowInfosChanged(
891 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
894 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
896
897 // Both foreground window and its wallpaper should receive the touch down
898 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700899 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800900
901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700902 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700903 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
905
906 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700907 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800908
909 // Wallpaper closes its channel, but the window remains.
910 wallpaperWindow->destroyReceiver();
911 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
912
913 // Now the foreground window goes away, but the wallpaper stays, even though its channel
914 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700915 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800916 foregroundWindow->consumeMotionCancel();
917}
918
Linnan Li72352222024-04-12 18:55:57 +0800919/**
920 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
921 * down event to the left window. Device B sends a down event to the right window. Next, the right
922 * window disappears. Both the right window and its wallpaper window should receive cancel event.
923 * The left window and its wallpaper window should not receive any events.
924 */
925TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
927 sp<FakeWindowHandle> leftForegroundWindow =
928 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700929 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800930 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
931 leftForegroundWindow->setDupTouchToWallpaper(true);
932 sp<FakeWindowHandle> leftWallpaperWindow =
933 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700934 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800935 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
936 leftWallpaperWindow->setIsWallpaper(true);
937
938 sp<FakeWindowHandle> rightForegroundWindow =
939 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700940 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800941 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
942 rightForegroundWindow->setDupTouchToWallpaper(true);
943 sp<FakeWindowHandle> rightWallpaperWindow =
944 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700945 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800946 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
947 rightWallpaperWindow->setIsWallpaper(true);
948
949 mDispatcher->onWindowInfosChanged(
950 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
951 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
952 {},
953 0,
954 0});
955
956 const DeviceId deviceA = 9;
957 const DeviceId deviceB = 3;
958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
959 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
960 .deviceId(deviceA)
961 .build());
962 leftForegroundWindow->consumeMotionEvent(
963 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
964 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
965 WithDeviceId(deviceA),
966 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
967
968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
969 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
970 .deviceId(deviceB)
971 .build());
972 rightForegroundWindow->consumeMotionEvent(
973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
974 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
975 WithDeviceId(deviceB),
976 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
977
978 // Now right foreground window disappears, but right wallpaper window remains.
979 mDispatcher->onWindowInfosChanged(
980 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
981 *rightWallpaperWindow->getInfo()},
982 {},
983 0,
984 0});
985
986 // Left foreground window and left wallpaper window still exist, and should not receive any
987 // events.
988 leftForegroundWindow->assertNoEvents();
989 leftWallpaperWindow->assertNoEvents();
990 // Since right foreground window disappeared, right wallpaper window and right foreground window
991 // should receive cancel events.
992 rightForegroundWindow->consumeMotionEvent(
993 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
994 rightWallpaperWindow->consumeMotionEvent(
995 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
996 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
997}
998
999/**
1000 * Three windows arranged horizontally and without any overlap. Every window has a
1001 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1002 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1003 * Next, device B sends move event to the right window. Touch for device B should slip from the
1004 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1005 * The middle window and its wallpaper window should receive a cancel event. The left window should
1006 * not receive any events. If device B continues to report events, the right window and its
1007 * wallpaper window should receive remaining events.
1008 */
1009TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1011 sp<FakeWindowHandle> leftForegroundWindow =
1012 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001013 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001014 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1015 leftForegroundWindow->setDupTouchToWallpaper(true);
1016 sp<FakeWindowHandle> leftWallpaperWindow =
1017 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001018 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001019 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1020 leftWallpaperWindow->setIsWallpaper(true);
1021
1022 sp<FakeWindowHandle> middleForegroundWindow =
1023 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001024 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001025 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1026 middleForegroundWindow->setDupTouchToWallpaper(true);
1027 middleForegroundWindow->setSlippery(true);
1028 sp<FakeWindowHandle> middleWallpaperWindow =
1029 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001030 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001031 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1032 middleWallpaperWindow->setIsWallpaper(true);
1033
1034 sp<FakeWindowHandle> rightForegroundWindow =
1035 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001036 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001037 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1038 rightForegroundWindow->setDupTouchToWallpaper(true);
1039 sp<FakeWindowHandle> rightWallpaperWindow =
1040 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001041 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001042 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1043 rightWallpaperWindow->setIsWallpaper(true);
1044
1045 mDispatcher->onWindowInfosChanged(
1046 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1047 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1048 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1049 {},
1050 0,
1051 0});
1052
1053 const DeviceId deviceA = 9;
1054 const DeviceId deviceB = 3;
1055 // Device A sends a DOWN event to the left window
1056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1057 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1058 .deviceId(deviceA)
1059 .build());
1060 leftForegroundWindow->consumeMotionEvent(
1061 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1062 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1063 WithDeviceId(deviceA),
1064 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1065 // Device B sends a DOWN event to the middle window
1066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1067 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1068 .deviceId(deviceB)
1069 .build());
1070 middleForegroundWindow->consumeMotionEvent(
1071 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1072 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1073 WithDeviceId(deviceB),
1074 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1075 // Move the events of device B to the top of the right window.
1076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1077 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1078 .deviceId(deviceB)
1079 .build());
1080 middleForegroundWindow->consumeMotionEvent(
1081 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1082 middleWallpaperWindow->consumeMotionEvent(
1083 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1084 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1085 rightForegroundWindow->consumeMotionEvent(
1086 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1087 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1088 WithDeviceId(deviceB),
1089 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1090 // Make sure the window on the right can receive the remaining events.
1091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1092 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1093 .deviceId(deviceB)
1094 .build());
1095 leftForegroundWindow->assertNoEvents();
1096 leftWallpaperWindow->assertNoEvents();
1097 middleForegroundWindow->assertNoEvents();
1098 middleWallpaperWindow->assertNoEvents();
1099 rightForegroundWindow->consumeMotionEvent(
1100 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1101 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1102 WithDeviceId(deviceB),
1103 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1104}
1105
1106/**
1107 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1108 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1109 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1110 * event to the middle window and then touch is transferred from the middle window to the right
1111 * window. The right window and its wallpaper window should receive a down event. The middle window
1112 * and its wallpaper window should receive a cancel event. The left window should not receive any
1113 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1114 */
1115TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1117 sp<FakeWindowHandle> leftForegroundWindow =
1118 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001119 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001120 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1121 leftForegroundWindow->setDupTouchToWallpaper(true);
1122 sp<FakeWindowHandle> leftWallpaperWindow =
1123 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001124 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001125 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1126 leftWallpaperWindow->setIsWallpaper(true);
1127
1128 sp<FakeWindowHandle> middleForegroundWindow =
1129 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001130 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001131 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1132 middleForegroundWindow->setDupTouchToWallpaper(true);
1133 sp<FakeWindowHandle> middleWallpaperWindow =
1134 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001135 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001136 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1137 middleWallpaperWindow->setIsWallpaper(true);
1138
1139 sp<FakeWindowHandle> rightForegroundWindow =
1140 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001141 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001142 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1143 rightForegroundWindow->setDupTouchToWallpaper(true);
1144 sp<FakeWindowHandle> rightWallpaperWindow =
1145 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001146 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001147 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1148 rightWallpaperWindow->setIsWallpaper(true);
1149
1150 mDispatcher->onWindowInfosChanged(
1151 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1152 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1153 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1154 {},
1155 0,
1156 0});
1157
1158 const DeviceId deviceA = 9;
1159 const DeviceId deviceB = 3;
1160 // Device A touch down on the left window
1161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1162 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1163 .deviceId(deviceA)
1164 .build());
1165 leftForegroundWindow->consumeMotionEvent(
1166 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1167 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1168 WithDeviceId(deviceA),
1169 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1170 // Device B touch down on the middle window
1171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1172 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1173 .deviceId(deviceB)
1174 .build());
1175 middleForegroundWindow->consumeMotionEvent(
1176 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1177 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1178 WithDeviceId(deviceB),
1179 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1180
1181 // Transfer touch from the middle window to the right window.
1182 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1183 rightForegroundWindow->getToken()));
1184
1185 middleForegroundWindow->consumeMotionEvent(
1186 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1187 middleWallpaperWindow->consumeMotionEvent(
1188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1189 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1190 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1191 WithDeviceId(deviceB),
1192 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1193 rightWallpaperWindow->consumeMotionEvent(
1194 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1195 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1196
1197 // Make sure the right window can receive the remaining events.
1198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1199 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1200 .deviceId(deviceB)
1201 .build());
1202 leftForegroundWindow->assertNoEvents();
1203 leftWallpaperWindow->assertNoEvents();
1204 middleForegroundWindow->assertNoEvents();
1205 middleWallpaperWindow->assertNoEvents();
1206 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1207 WithDeviceId(deviceB),
1208 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1209 rightWallpaperWindow->consumeMotionEvent(
1210 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1211 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1212}
1213
Arthur Hungc539dbb2022-12-08 07:45:36 +00001214class ShouldSplitTouchFixture : public InputDispatcherTest,
1215 public ::testing::WithParamInterface<bool> {};
1216INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1217 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001218/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001219 * A single window that receives touch (on top), and a wallpaper window underneath it.
1220 * The top window gets a multitouch gesture.
1221 * Ensure that wallpaper gets the same gesture.
1222 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001223TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001225 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001226 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1227 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001228 foregroundWindow->setDupTouchToWallpaper(true);
1229 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001230
1231 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001232 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1233 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001234 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001235
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001236 mDispatcher->onWindowInfosChanged(
1237 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001238
1239 // Touch down on top window
1240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001241 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1242 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1244
1245 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001246 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001247 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001248
1249 // Second finger down on the top window
1250 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001251 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001252 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001253 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1254 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001255 .build();
1256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001257 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001258 InputEventInjectionSync::WAIT_FOR_RESULT))
1259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001260 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001261 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001262 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001263
1264 const MotionEvent secondFingerUpEvent =
1265 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001266 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001267 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001268 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1269 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001270 .build();
1271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001272 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001273 InputEventInjectionSync::WAIT_FOR_RESULT))
1274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001275 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1276 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1277 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1278 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1279 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001280
1281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001283 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1284 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001285 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001286 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001287 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001288 .x(100)
1289 .y(100))
1290 .build(),
1291 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001293 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1294 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001295}
1296
1297/**
1298 * Two windows: a window on the left and window on the right.
1299 * A third window, wallpaper, is behind both windows, and spans both top windows.
1300 * The first touch down goes to the left window. A second pointer touches down on the right window.
1301 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1302 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1303 * ACTION_POINTER_DOWN(1).
1304 */
1305TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001307 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1308 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001309 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001310 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001311
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001312 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1313 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001314 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001315 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001316
1317 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001318 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1319 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001320 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001321 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001322
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001323 mDispatcher->onWindowInfosChanged(
1324 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1325 {},
1326 0,
1327 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001328
1329 // Touch down on left window
1330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001331 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1332 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1334
1335 // Both foreground window and its wallpaper should receive the touch down
1336 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001337 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001338
1339 // Second finger down on the right window
1340 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001341 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001342 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001343 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1344 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001345 .build();
1346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001347 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001348 InputEventInjectionSync::WAIT_FOR_RESULT))
1349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1350
1351 leftWindow->consumeMotionMove();
1352 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001353 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1354 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001355 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001356
1357 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001358 mDispatcher->onWindowInfosChanged(
1359 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001360 leftWindow->consumeMotionCancel();
1361 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001362 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001363
1364 // The pointer that's still down on the right window moves, and goes to the right window only.
1365 // As far as the dispatcher's concerned though, both pointers are still present.
1366 const MotionEvent secondFingerMoveEvent =
1367 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1368 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001369 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1370 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001371 .build();
1372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001373 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001374 InputEventInjectionSync::WAIT_FOR_RESULT));
1375 rightWindow->consumeMotionMove();
1376
1377 leftWindow->assertNoEvents();
1378 rightWindow->assertNoEvents();
1379 wallpaperWindow->assertNoEvents();
1380}
1381
Arthur Hungc539dbb2022-12-08 07:45:36 +00001382/**
1383 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1384 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1385 * The right window should receive ACTION_DOWN.
1386 */
1387TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001389 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1390 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001391 leftWindow->setFrame(Rect(0, 0, 200, 200));
1392 leftWindow->setDupTouchToWallpaper(true);
1393 leftWindow->setSlippery(true);
1394
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001395 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1396 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001397 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001398
1399 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001400 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1401 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001402 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001403
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001404 mDispatcher->onWindowInfosChanged(
1405 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1406 {},
1407 0,
1408 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001409
Arthur Hungc539dbb2022-12-08 07:45:36 +00001410 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001412 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1413 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001415
1416 // Both foreground window and its wallpaper should receive the touch down
1417 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001418 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001419
Arthur Hungc539dbb2022-12-08 07:45:36 +00001420 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001422 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001423 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1425
Arthur Hungc539dbb2022-12-08 07:45:36 +00001426 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001427 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1428 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001429}
1430
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001431/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001432 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1433 * interactive, it might stop sending this flag.
1434 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1435 * to have a consistent input stream.
1436 *
1437 * Test procedure:
1438 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1439 * DOWN (new gesture).
1440 *
1441 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1442 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1443 *
1444 * We technically just need a single window here, but we are using two windows (spy on top and a
1445 * regular window below) to emulate the actual situation where it happens on the device.
1446 */
1447TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001449 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1450 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001451 spyWindow->setFrame(Rect(0, 0, 200, 200));
1452 spyWindow->setTrustedOverlay(true);
1453 spyWindow->setSpy(true);
1454
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001455 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1456 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001457 window->setFrame(Rect(0, 0, 200, 200));
1458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001459 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001460 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001461
1462 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001463 mDispatcher->notifyMotion(
1464 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1465 .deviceId(touchDeviceId)
1466 .policyFlags(DEFAULT_POLICY_FLAGS)
1467 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1468 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001469
Prabir Pradhan678438e2023-04-13 19:32:51 +00001470 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1471 .deviceId(touchDeviceId)
1472 .policyFlags(DEFAULT_POLICY_FLAGS)
1473 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1474 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1475 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001476 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1477 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1478 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1479 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1480
1481 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001482 mDispatcher->notifyMotion(
1483 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1484 .deviceId(touchDeviceId)
1485 .policyFlags(0)
1486 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1487 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1488 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001489 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1490 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1491
1492 // We don't need to reset the device to reproduce the issue, but the reset event typically
1493 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001494 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001495
1496 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001497 mDispatcher->notifyMotion(
1498 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1499 .deviceId(touchDeviceId)
1500 .policyFlags(DEFAULT_POLICY_FLAGS)
1501 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1502 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001503 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1504 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1505
1506 // No more events
1507 spyWindow->assertNoEvents();
1508 window->assertNoEvents();
1509}
1510
1511/**
Linnan Li907ae732023-09-05 17:14:21 +08001512 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1513 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1514 * interactive, it might stop sending this flag.
1515 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1516 * the consistency of the hover event in this case.
1517 *
1518 * Test procedure:
1519 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1520 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1521 *
1522 * We expect to receive two full streams of hover events.
1523 */
1524TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1526
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1528 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001529 window->setFrame(Rect(0, 0, 300, 300));
1530
1531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1532
1533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1534 .policyFlags(DEFAULT_POLICY_FLAGS)
1535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1536 .build());
1537 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1538
1539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1540 .policyFlags(DEFAULT_POLICY_FLAGS)
1541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1542 .build());
1543 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1544
1545 // Send hover exit without the default policy flags.
1546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1547 .policyFlags(0)
1548 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1549 .build());
1550
1551 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1552
1553 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1554 // right event.
1555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1556 .policyFlags(DEFAULT_POLICY_FLAGS)
1557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1558 .build());
1559 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1560
1561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1562 .policyFlags(DEFAULT_POLICY_FLAGS)
1563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1564 .build());
1565 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1566
1567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1568 .policyFlags(DEFAULT_POLICY_FLAGS)
1569 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1570 .build());
1571 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1572}
1573
1574/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001575 * Two windows: a window on the left and a window on the right.
1576 * Mouse is hovered from the right window into the left window.
1577 * Next, we tap on the left window, where the cursor was last seen.
1578 * The second tap is done onto the right window.
1579 * The mouse and tap are from two different devices.
1580 * We technically don't need to set the downtime / eventtime for these events, but setting these
1581 * explicitly helps during debugging.
1582 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1583 * In the buggy implementation, a tap on the right window would cause a crash.
1584 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001585TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1586 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1587
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001589 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1590 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001591 leftWindow->setFrame(Rect(0, 0, 200, 200));
1592
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001593 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1594 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001595 rightWindow->setFrame(Rect(200, 0, 400, 200));
1596
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001597 mDispatcher->onWindowInfosChanged(
1598 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001599 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1600 // stale.
1601 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1602 const int32_t mouseDeviceId = 6;
1603 const int32_t touchDeviceId = 4;
1604 // Move the cursor from right
1605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001606 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001607 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1608 AINPUT_SOURCE_MOUSE)
1609 .deviceId(mouseDeviceId)
1610 .downTime(baseTime + 10)
1611 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001612 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001613 .build()));
1614 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1615
1616 // .. to the left window
1617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001619 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1620 AINPUT_SOURCE_MOUSE)
1621 .deviceId(mouseDeviceId)
1622 .downTime(baseTime + 10)
1623 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001624 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001625 .build()));
1626 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1628 // Now tap the left window
1629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001630 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001631 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1632 AINPUT_SOURCE_TOUCHSCREEN)
1633 .deviceId(touchDeviceId)
1634 .downTime(baseTime + 40)
1635 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001636 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001637 .build()));
1638 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1639 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1640
1641 // release tap
1642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001643 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001644 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1645 AINPUT_SOURCE_TOUCHSCREEN)
1646 .deviceId(touchDeviceId)
1647 .downTime(baseTime + 40)
1648 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001649 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001650 .build()));
1651 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1652
1653 // Tap the window on the right
1654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001655 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001656 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1657 AINPUT_SOURCE_TOUCHSCREEN)
1658 .deviceId(touchDeviceId)
1659 .downTime(baseTime + 60)
1660 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001661 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001662 .build()));
1663 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1664
1665 // release tap
1666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001667 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001668 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1669 AINPUT_SOURCE_TOUCHSCREEN)
1670 .deviceId(touchDeviceId)
1671 .downTime(baseTime + 60)
1672 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001673 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001674 .build()));
1675 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1676
1677 // No more events
1678 leftWindow->assertNoEvents();
1679 rightWindow->assertNoEvents();
1680}
1681
1682/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001683 * Two windows: a window on the left and a window on the right.
1684 * Mouse is hovered from the right window into the left window.
1685 * Next, we tap on the left window, where the cursor was last seen.
1686 * The second tap is done onto the right window.
1687 * The mouse and tap are from two different devices.
1688 * We technically don't need to set the downtime / eventtime for these events, but setting these
1689 * explicitly helps during debugging.
1690 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1691 * In the buggy implementation, a tap on the right window would cause a crash.
1692 */
1693TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1694 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1695
1696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001697 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1698 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001699 leftWindow->setFrame(Rect(0, 0, 200, 200));
1700
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001701 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1702 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001703 rightWindow->setFrame(Rect(200, 0, 400, 200));
1704
1705 mDispatcher->onWindowInfosChanged(
1706 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1707 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1708 // stale.
1709 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1710 const int32_t mouseDeviceId = 6;
1711 const int32_t touchDeviceId = 4;
1712 // Move the cursor from right
1713 mDispatcher->notifyMotion(
1714 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1715 .deviceId(mouseDeviceId)
1716 .downTime(baseTime + 10)
1717 .eventTime(baseTime + 20)
1718 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1719 .build());
1720 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1721
1722 // .. to the left window
1723 mDispatcher->notifyMotion(
1724 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1725 .deviceId(mouseDeviceId)
1726 .downTime(baseTime + 10)
1727 .eventTime(baseTime + 30)
1728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1729 .build());
1730 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1731 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1732 // Now tap the left window
1733 mDispatcher->notifyMotion(
1734 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1735 .deviceId(touchDeviceId)
1736 .downTime(baseTime + 40)
1737 .eventTime(baseTime + 40)
1738 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1739 .build());
1740 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1741
1742 // release tap
1743 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1744 .deviceId(touchDeviceId)
1745 .downTime(baseTime + 40)
1746 .eventTime(baseTime + 50)
1747 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1748 .build());
1749 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1750
1751 // Tap the window on the right
1752 mDispatcher->notifyMotion(
1753 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1754 .deviceId(touchDeviceId)
1755 .downTime(baseTime + 60)
1756 .eventTime(baseTime + 60)
1757 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1758 .build());
1759 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1760
1761 // release tap
1762 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1763 .deviceId(touchDeviceId)
1764 .downTime(baseTime + 60)
1765 .eventTime(baseTime + 70)
1766 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1767 .build());
1768 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1769
1770 // No more events
1771 leftWindow->assertNoEvents();
1772 rightWindow->assertNoEvents();
1773}
1774
1775/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001776 * Start hovering in a window. While this hover is still active, make another window appear on top.
1777 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1778 * While the top window is present, the hovering is stopped.
1779 * Later, hovering gets resumed again.
1780 * Ensure that new hover gesture is handled correctly.
1781 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1782 * to the window that's currently being hovered over.
1783 */
1784TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1787 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001788 window->setFrame(Rect(0, 0, 200, 200));
1789
1790 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001792
1793 // Start hovering in the window
1794 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1796 .build());
1797 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1798
1799 // Now, an obscuring window appears!
1800 sp<FakeWindowHandle> obscuringWindow =
1801 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001802 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001803 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001804 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1805 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1806 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1807 obscuringWindow->setNoInputChannel(true);
1808 obscuringWindow->setFocusable(false);
1809 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001810 mDispatcher->onWindowInfosChanged(
1811 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001812
1813 // While this new obscuring window is present, the hovering is stopped
1814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1815 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1816 .build());
1817 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1818
1819 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001821
1822 // And a new hover gesture starts.
1823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1825 .build());
1826 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1827}
1828
1829/**
1830 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1831 * the obscuring window.
1832 */
1833TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001835 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1836 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001837 window->setFrame(Rect(0, 0, 200, 200));
1838
1839 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001841
1842 // Start hovering in the window
1843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1845 .build());
1846 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1847
1848 // Now, an obscuring window appears!
1849 sp<FakeWindowHandle> obscuringWindow =
1850 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001851 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001852 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001853 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1854 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1855 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1856 obscuringWindow->setNoInputChannel(true);
1857 obscuringWindow->setFocusable(false);
1858 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001859 mDispatcher->onWindowInfosChanged(
1860 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001861
1862 // While this new obscuring window is present, the hovering continues. The event can't go to the
1863 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1864 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1865 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1866 .build());
1867 obscuringWindow->assertNoEvents();
1868 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1869
1870 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001872
1873 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1874 // so it should generate a HOVER_ENTER
1875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1876 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1877 .build());
1878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1879
1880 // Now the MOVE should be getting dispatched normally
1881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1882 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1883 .build());
1884 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1885}
1886
1887/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001888 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1889 * events are delivered to the window.
1890 */
1891TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001893 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1894 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001895 window->setFrame(Rect(0, 0, 200, 200));
1896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1897
1898 // Start hovering in the window
1899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1901 .build());
1902 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1903
1904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1906 .build());
1907 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1908
1909 // Scroll with the mouse
1910 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1912 .build());
1913 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1914}
1915
Siarhei Vishniakoub711e652024-08-12 12:00:28 -07001916/**
1917 * Two windows: a trusted overlay and a regular window underneath. Both windows are visible.
1918 * Mouse is hovered, and the hover event should only go to the overlay.
1919 * However, next, the touchable region of the trusted overlay shrinks. The mouse position hasn't
1920 * changed, but the cursor would now end up hovering above the regular window underneatch.
1921 * If the mouse is now clicked, this would generate an ACTION_DOWN event, which would go to the
1922 * regular window. However, the trusted overlay is also watching for outside touch.
1923 * The trusted overlay should get two events:
1924 * 1) The ACTION_OUTSIDE event, since the click is now not inside its touchable region
1925 * 2) The HOVER_EXIT event, since the mouse pointer is no longer hovering inside this window
1926 *
1927 * This test reproduces a crash where there is an overlap between dispatch modes for the trusted
1928 * overlay touch target, since the event is causing both an ACTION_OUTSIDE, and as a HOVER_EXIT.
1929 */
1930TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlay) {
1931 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1932 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1933 ui::LogicalDisplayId::DEFAULT);
1934 overlay->setTrustedOverlay(true);
1935 overlay->setWatchOutsideTouch(true);
1936 overlay->setFrame(Rect(0, 0, 200, 200));
1937
1938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1939 ui::LogicalDisplayId::DEFAULT);
1940 window->setFrame(Rect(0, 0, 200, 200));
1941
1942 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1943 // Hover the mouse into the overlay
1944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1945 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1946 .build());
1947 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1948
1949 // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1950 // the regular window as the touch target
1951 overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1952 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1953
1954 // Now we can click with the mouse. The click should go into the regular window
1955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1956 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1957 .build());
1958 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1959 overlay->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
1960 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1961}
1962
1963/**
1964 * Similar to above, but also has a spy on top that also catches the HOVER
1965 * events. Also, instead of ACTION_DOWN, we are continuing to send the hovering
1966 * stream to ensure that the spy receives hover events correctly.
1967 */
1968TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlayWithSpy) {
1969 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1970 sp<FakeWindowHandle> spyWindow =
1971 sp<FakeWindowHandle>::make(app, mDispatcher, "Spy", ui::LogicalDisplayId::DEFAULT);
1972 spyWindow->setFrame(Rect(0, 0, 200, 200));
1973 spyWindow->setTrustedOverlay(true);
1974 spyWindow->setSpy(true);
1975 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1976 ui::LogicalDisplayId::DEFAULT);
1977 overlay->setTrustedOverlay(true);
1978 overlay->setWatchOutsideTouch(true);
1979 overlay->setFrame(Rect(0, 0, 200, 200));
1980
1981 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1982 ui::LogicalDisplayId::DEFAULT);
1983 window->setFrame(Rect(0, 0, 200, 200));
1984
1985 mDispatcher->onWindowInfosChanged(
1986 {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1987 // Hover the mouse into the overlay
1988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1989 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1990 .build());
1991 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1992 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1993
1994 // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1995 // the regular window as the touch target
1996 overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1997 mDispatcher->onWindowInfosChanged(
1998 {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1999
2000 // Now we can click with the mouse. The click should go into the regular window
2001 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2003 .build());
2004 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2005 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2006 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2007}
2008
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002009using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2010
2011/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002012 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2013 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002014 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002015TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002016 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002018 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2019 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002020 window->setFrame(Rect(0, 0, 200, 200));
2021
2022 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2023
2024 constexpr int32_t touchDeviceId = 4;
2025 constexpr int32_t stylusDeviceId = 2;
2026
2027 // Stylus down
2028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2029 .deviceId(stylusDeviceId)
2030 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2031 .build());
2032 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2033
2034 // Touch down
2035 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2036 .deviceId(touchDeviceId)
2037 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2038 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002039
2040 // Touch move
2041 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2042 .deviceId(touchDeviceId)
2043 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2044 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002045 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002046
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002047 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2049 .deviceId(stylusDeviceId)
2050 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2051 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002052 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2053 WithCoords(101, 111)));
2054
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002055 window->assertNoEvents();
2056}
2057
2058/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002059 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2060 * touch is not dropped, because multiple devices are allowed to be active in the same window.
2061 */
2062TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
2063 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002065 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2066 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002067 window->setFrame(Rect(0, 0, 200, 200));
2068
2069 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2070
2071 constexpr int32_t touchDeviceId = 4;
2072 constexpr int32_t stylusDeviceId = 2;
2073
2074 // Stylus down
2075 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2076 .deviceId(stylusDeviceId)
2077 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2078 .build());
2079 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2080
2081 // Touch down
2082 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2083 .deviceId(touchDeviceId)
2084 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2085 .build());
2086 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2087
2088 // Touch move
2089 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2090 .deviceId(touchDeviceId)
2091 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2092 .build());
2093 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2094
2095 // Stylus move
2096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2097 .deviceId(stylusDeviceId)
2098 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2099 .build());
2100 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2101 WithCoords(101, 111)));
2102
2103 window->assertNoEvents();
2104}
2105
2106/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002107 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002108 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002109 * Similar test as above, but with added SPY window.
2110 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002111TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002112 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002114 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2115 ui::LogicalDisplayId::DEFAULT);
2116 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2117 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002118 spyWindow->setFrame(Rect(0, 0, 200, 200));
2119 spyWindow->setTrustedOverlay(true);
2120 spyWindow->setSpy(true);
2121 window->setFrame(Rect(0, 0, 200, 200));
2122
2123 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2124
2125 constexpr int32_t touchDeviceId = 4;
2126 constexpr int32_t stylusDeviceId = 2;
2127
2128 // Stylus down
2129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2130 .deviceId(stylusDeviceId)
2131 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2132 .build());
2133 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2134 spyWindow->consumeMotionEvent(
2135 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2136
2137 // Touch down
2138 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2139 .deviceId(touchDeviceId)
2140 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2141 .build());
2142
2143 // Touch move
2144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2145 .deviceId(touchDeviceId)
2146 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2147 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002148
2149 // Touch is ignored because stylus is already down
2150
2151 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2153 .deviceId(stylusDeviceId)
2154 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2155 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002156 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2157 WithCoords(101, 111)));
2158 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2159 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002160
2161 window->assertNoEvents();
2162 spyWindow->assertNoEvents();
2163}
2164
2165/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002166 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2167 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2168 * Similar test as above, but with added SPY window.
2169 */
2170TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2171 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002173 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2174 ui::LogicalDisplayId::DEFAULT);
2175 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2176 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002177 spyWindow->setFrame(Rect(0, 0, 200, 200));
2178 spyWindow->setTrustedOverlay(true);
2179 spyWindow->setSpy(true);
2180 window->setFrame(Rect(0, 0, 200, 200));
2181
2182 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2183
2184 constexpr int32_t touchDeviceId = 4;
2185 constexpr int32_t stylusDeviceId = 2;
2186
2187 // Stylus down
2188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2189 .deviceId(stylusDeviceId)
2190 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2191 .build());
2192 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2193 spyWindow->consumeMotionEvent(
2194 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2195
2196 // Touch down
2197 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2198 .deviceId(touchDeviceId)
2199 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2200 .build());
2201 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2202 spyWindow->consumeMotionEvent(
2203 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2204
2205 // Touch move
2206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2207 .deviceId(touchDeviceId)
2208 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2209 .build());
2210 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2211 spyWindow->consumeMotionEvent(
2212 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2213
2214 // Subsequent stylus movements are delivered correctly
2215 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2216 .deviceId(stylusDeviceId)
2217 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2218 .build());
2219 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2220 WithCoords(101, 111)));
2221 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2222 WithCoords(101, 111)));
2223
2224 window->assertNoEvents();
2225 spyWindow->assertNoEvents();
2226}
2227
2228/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002229 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002230 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002231 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002232TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002233 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002235 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2236 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002237 window->setFrame(Rect(0, 0, 200, 200));
2238
2239 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2240
2241 constexpr int32_t touchDeviceId = 4;
2242 constexpr int32_t stylusDeviceId = 2;
2243
2244 // Stylus down on the window
2245 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2246 .deviceId(stylusDeviceId)
2247 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2248 .build());
2249 window->consumeMotionEvent(
2250 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2251
2252 // Touch down on window
2253 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2254 .deviceId(touchDeviceId)
2255 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2256 .build());
2257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2258 .deviceId(touchDeviceId)
2259 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2260 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002261
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002262 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002263
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002264 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2266 .deviceId(stylusDeviceId)
2267 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2268 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002269 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2270 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002271
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002272 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002273 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2274 .deviceId(touchDeviceId)
2275 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2276 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002277 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002278}
2279
2280/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002281 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2282 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2283 */
2284TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2285 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2286 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002287 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2288 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002289 window->setFrame(Rect(0, 0, 200, 200));
2290
2291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2292
2293 constexpr int32_t touchDeviceId = 4;
2294 constexpr int32_t stylusDeviceId = 2;
2295
2296 // Stylus down on the window
2297 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2298 .deviceId(stylusDeviceId)
2299 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2300 .build());
2301 window->consumeMotionEvent(
2302 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2303
2304 // Touch down on window
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2306 .deviceId(touchDeviceId)
2307 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2308 .build());
2309 // Touch move on window
2310 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2311 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2312 .deviceId(touchDeviceId)
2313 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2314 .build());
2315 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2316
2317 // Subsequent stylus movements are delivered correctly
2318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2319 .deviceId(stylusDeviceId)
2320 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2321 .build());
2322 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2323 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2324
2325 // and subsequent touches continue to work
2326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2327 .deviceId(touchDeviceId)
2328 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2329 .build());
2330 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2331 window->assertNoEvents();
2332}
2333
2334/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002335 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002336 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002337 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002338TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002339 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002341 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2342 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002343 window->setFrame(Rect(0, 0, 200, 200));
2344
2345 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2346
2347 constexpr int32_t touchDeviceId = 4;
2348 constexpr int32_t stylusDeviceId = 2;
2349
2350 // Touch down on window
2351 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2352 .deviceId(touchDeviceId)
2353 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2354 .build());
2355 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2356 .deviceId(touchDeviceId)
2357 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2358 .build());
2359 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2360 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2361
2362 // Stylus hover on the window
2363 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2364 .deviceId(stylusDeviceId)
2365 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2366 .build());
2367 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2368 .deviceId(stylusDeviceId)
2369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2370 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002371 // Stylus hover movement causes touch to be canceled
2372 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2373 WithCoords(141, 146)));
2374 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2375 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2376 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2377 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002378
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002379 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2381 .deviceId(touchDeviceId)
2382 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2383 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002384
2385 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002386}
2387
2388/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002389 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2390 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2391 */
2392TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2393 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2396 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002397 window->setFrame(Rect(0, 0, 200, 200));
2398
2399 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2400
2401 constexpr int32_t touchDeviceId = 4;
2402 constexpr int32_t stylusDeviceId = 2;
2403
2404 // Touch down on window
2405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2406 .deviceId(touchDeviceId)
2407 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2408 .build());
2409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2410 .deviceId(touchDeviceId)
2411 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2412 .build());
2413 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2414 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2415
2416 // Stylus hover on the window
2417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2418 .deviceId(stylusDeviceId)
2419 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2420 .build());
2421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2422 .deviceId(stylusDeviceId)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2424 .build());
2425 // Stylus hover movement is received normally
2426 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2427 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2428 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2429 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2430
2431 // Subsequent touch movements also work
2432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2433 .deviceId(touchDeviceId)
2434 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2435 .build());
2436 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2437 WithCoords(142, 147)));
2438
2439 window->assertNoEvents();
2440}
2441
2442/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002443 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2444 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2445 * become active.
2446 */
2447TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002448 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002450 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2451 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002452 window->setFrame(Rect(0, 0, 200, 200));
2453
2454 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2455
2456 constexpr int32_t stylusDeviceId1 = 3;
2457 constexpr int32_t stylusDeviceId2 = 5;
2458
2459 // Touch down on window
2460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2461 .deviceId(stylusDeviceId1)
2462 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2463 .build());
2464 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2465 .deviceId(stylusDeviceId1)
2466 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2467 .build());
2468 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2469 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2470
2471 // Second stylus down
2472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2473 .deviceId(stylusDeviceId2)
2474 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2475 .build());
2476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2477 .deviceId(stylusDeviceId2)
2478 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2479 .build());
2480
2481 // First stylus is canceled, second one takes over.
2482 window->consumeMotionEvent(
2483 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2484 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2486
2487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2488 .deviceId(stylusDeviceId1)
2489 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2490 .build());
2491 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002492 window->assertNoEvents();
2493}
2494
2495/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002496 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2497 * both stylus devices can function simultaneously.
2498 */
2499TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2500 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2501 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002502 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2503 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002504 window->setFrame(Rect(0, 0, 200, 200));
2505
2506 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2507
2508 constexpr int32_t stylusDeviceId1 = 3;
2509 constexpr int32_t stylusDeviceId2 = 5;
2510
2511 // Touch down on window
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2513 .deviceId(stylusDeviceId1)
2514 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2515 .build());
2516 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2517 .deviceId(stylusDeviceId1)
2518 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2519 .build());
2520 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2521 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2522
2523 // Second stylus down
2524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2525 .deviceId(stylusDeviceId2)
2526 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2527 .build());
2528 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2529 .deviceId(stylusDeviceId2)
2530 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2531 .build());
2532 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2533 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2534
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2536 .deviceId(stylusDeviceId1)
2537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2538 .build());
2539 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2540 window->assertNoEvents();
2541}
2542
2543/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002544 * One window. Touch down on the window. Then, stylus down on the window from another device.
2545 * Ensure that is canceled, because stylus down should be preferred over touch.
2546 */
2547TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002548 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2551 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002552 window->setFrame(Rect(0, 0, 200, 200));
2553
2554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2555
2556 constexpr int32_t touchDeviceId = 4;
2557 constexpr int32_t stylusDeviceId = 2;
2558
2559 // Touch down on window
2560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2561 .deviceId(touchDeviceId)
2562 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2563 .build());
2564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2565 .deviceId(touchDeviceId)
2566 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2567 .build());
2568 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2569 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2570
2571 // Stylus down on the window
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2573 .deviceId(stylusDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2575 .build());
2576 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2577 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2578
2579 // Subsequent stylus movements are delivered correctly
2580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2581 .deviceId(stylusDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2583 .build());
2584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2585 WithCoords(101, 111)));
2586}
2587
2588/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002589 * One window. Touch down on the window. Then, stylus down on the window from another device.
2590 * Ensure that both touch and stylus are functioning independently.
2591 */
2592TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2593 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002595 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2596 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002597 window->setFrame(Rect(0, 0, 200, 200));
2598
2599 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2600
2601 constexpr int32_t touchDeviceId = 4;
2602 constexpr int32_t stylusDeviceId = 2;
2603
2604 // Touch down on window
2605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2606 .deviceId(touchDeviceId)
2607 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2608 .build());
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2612 .build());
2613 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2614 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2615
2616 // Stylus down on the window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2618 .deviceId(stylusDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2620 .build());
2621 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2622
2623 // Subsequent stylus movements are delivered correctly
2624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2625 .deviceId(stylusDeviceId)
2626 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2627 .build());
2628 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2629 WithCoords(101, 111)));
2630
2631 // Touch continues to work too
2632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2633 .deviceId(touchDeviceId)
2634 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2635 .build());
2636 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2637}
2638
2639/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002640 * Two windows: a window on the left and a window on the right.
2641 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2642 * down. Then, on the left window, also place second touch pointer down.
2643 * This test tries to reproduce a crash.
2644 * In the buggy implementation, second pointer down on the left window would cause a crash.
2645 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002646TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2647 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002649 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2650 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002651 leftWindow->setFrame(Rect(0, 0, 200, 200));
2652
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002653 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2654 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002655 rightWindow->setFrame(Rect(200, 0, 400, 200));
2656
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002657 mDispatcher->onWindowInfosChanged(
2658 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002659
2660 const int32_t touchDeviceId = 4;
2661 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002662
2663 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2665 .deviceId(mouseDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002668 leftWindow->consumeMotionEvent(
2669 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2670
2671 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2673 .deviceId(mouseDeviceId)
2674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002677
2678 leftWindow->consumeMotionEvent(
2679 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2680 leftWindow->consumeMotionEvent(
2681 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2682
Prabir Pradhan678438e2023-04-13 19:32:51 +00002683 mDispatcher->notifyMotion(
2684 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2685 .deviceId(mouseDeviceId)
2686 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2687 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2688 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2689 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002690 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2691
2692 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
2695 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2696 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002697 leftWindow->assertNoEvents();
2698
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002699 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2700
2701 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002702 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2703 .deviceId(touchDeviceId)
2704 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2705 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2706 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002707 // Since this is now a new splittable pointer going down on the left window, and it's coming
2708 // from a different device, the current gesture in the left window (pointer down) should first
2709 // be canceled.
2710 leftWindow->consumeMotionEvent(
2711 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002712 leftWindow->consumeMotionEvent(
2713 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2714 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2715 // current implementation.
2716 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2717 rightWindow->consumeMotionEvent(
2718 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2719
2720 leftWindow->assertNoEvents();
2721 rightWindow->assertNoEvents();
2722}
2723
2724/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002725 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002726 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2727 * down. Then, on the left window, also place second touch pointer down.
2728 * This test tries to reproduce a crash.
2729 * In the buggy implementation, second pointer down on the left window would cause a crash.
2730 */
2731TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2732 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002734 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2735 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002736 leftWindow->setFrame(Rect(0, 0, 200, 200));
2737
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002738 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2739 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002740 rightWindow->setFrame(Rect(200, 0, 400, 200));
2741
2742 mDispatcher->onWindowInfosChanged(
2743 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2744
2745 const int32_t touchDeviceId = 4;
2746 const int32_t mouseDeviceId = 6;
2747
2748 // Start hovering over the left window
2749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2750 .deviceId(mouseDeviceId)
2751 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2752 .build());
2753 leftWindow->consumeMotionEvent(
2754 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2755
2756 // Mouse down on left window
2757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2758 .deviceId(mouseDeviceId)
2759 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2761 .build());
2762
2763 leftWindow->consumeMotionEvent(
2764 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2765 leftWindow->consumeMotionEvent(
2766 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2767
2768 mDispatcher->notifyMotion(
2769 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2770 .deviceId(mouseDeviceId)
2771 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2772 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2773 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2774 .build());
2775 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2776
2777 // First touch pointer down on right window
2778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2779 .deviceId(touchDeviceId)
2780 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2781 .build());
2782 leftWindow->assertNoEvents();
2783
2784 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2785
2786 // Second touch pointer down on left window
2787 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2788 .deviceId(touchDeviceId)
2789 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2790 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2791 .build());
2792 // Since this is now a new splittable pointer going down on the left window, and it's coming
2793 // from a different device, it will be split and delivered to left window separately.
2794 leftWindow->consumeMotionEvent(
2795 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2796 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2797 // current implementation.
2798 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2799 rightWindow->consumeMotionEvent(
2800 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2801
2802 leftWindow->assertNoEvents();
2803 rightWindow->assertNoEvents();
2804}
2805
2806/**
2807 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002808 * Mouse is hovered on the left window and stylus is hovered on the right window.
2809 */
2810TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002812 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2813 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002814 leftWindow->setFrame(Rect(0, 0, 200, 200));
2815
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002816 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2817 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002818 rightWindow->setFrame(Rect(200, 0, 400, 200));
2819
2820 mDispatcher->onWindowInfosChanged(
2821 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2822
2823 const int32_t stylusDeviceId = 3;
2824 const int32_t mouseDeviceId = 6;
2825
2826 // Start hovering over the left window
2827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2828 .deviceId(mouseDeviceId)
2829 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2830 .build());
2831 leftWindow->consumeMotionEvent(
2832 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2833
2834 // Stylus hovered on right window
2835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2836 .deviceId(stylusDeviceId)
2837 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2838 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002839 rightWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2841
2842 // Subsequent HOVER_MOVE events are dispatched correctly.
2843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2844 .deviceId(mouseDeviceId)
2845 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2846 .build());
2847 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002848 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002849
2850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2851 .deviceId(stylusDeviceId)
2852 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2853 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002854 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002855 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002856
2857 leftWindow->assertNoEvents();
2858 rightWindow->assertNoEvents();
2859}
2860
2861/**
2862 * Three windows: a window on the left and a window on the right.
2863 * And a spy window that's positioned above all of them.
2864 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2865 * Check the stream that's received by the spy.
2866 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002867TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2868 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002869 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2870
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002871 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2872 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002873 spyWindow->setFrame(Rect(0, 0, 400, 400));
2874 spyWindow->setTrustedOverlay(true);
2875 spyWindow->setSpy(true);
2876
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002877 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2878 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002879 leftWindow->setFrame(Rect(0, 0, 200, 200));
2880
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002881 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2882 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002883
2884 rightWindow->setFrame(Rect(200, 0, 400, 200));
2885
2886 mDispatcher->onWindowInfosChanged(
2887 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2888
2889 const int32_t stylusDeviceId = 1;
2890 const int32_t touchDeviceId = 2;
2891
2892 // Stylus down on the left window
2893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2894 .deviceId(stylusDeviceId)
2895 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2896 .build());
2897 leftWindow->consumeMotionEvent(
2898 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2899 spyWindow->consumeMotionEvent(
2900 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2901
2902 // Touch down on the right window
2903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2904 .deviceId(touchDeviceId)
2905 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2906 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002907 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002908 rightWindow->consumeMotionEvent(
2909 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002910
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002911 // Spy window does not receive touch events, because stylus events take precedence, and it
2912 // already has an active stylus gesture.
2913
2914 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2916 .deviceId(stylusDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2918 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002919 leftWindow->consumeMotionEvent(
2920 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2921 spyWindow->consumeMotionEvent(
2922 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002923
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002924 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2926 .deviceId(touchDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2928 .build());
2929 rightWindow->consumeMotionEvent(
2930 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002931
2932 spyWindow->assertNoEvents();
2933 leftWindow->assertNoEvents();
2934 rightWindow->assertNoEvents();
2935}
2936
2937/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002938 * Three windows: a window on the left and a window on the right.
2939 * And a spy window that's positioned above all of them.
2940 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2941 * Check the stream that's received by the spy.
2942 */
2943TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2944 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2946
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002947 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2948 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002949 spyWindow->setFrame(Rect(0, 0, 400, 400));
2950 spyWindow->setTrustedOverlay(true);
2951 spyWindow->setSpy(true);
2952
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002953 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2954 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002955 leftWindow->setFrame(Rect(0, 0, 200, 200));
2956
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002957 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2958 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002959
2960 rightWindow->setFrame(Rect(200, 0, 400, 200));
2961
2962 mDispatcher->onWindowInfosChanged(
2963 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2964
2965 const int32_t stylusDeviceId = 1;
2966 const int32_t touchDeviceId = 2;
2967
2968 // Stylus down on the left window
2969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2970 .deviceId(stylusDeviceId)
2971 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2972 .build());
2973 leftWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2975 spyWindow->consumeMotionEvent(
2976 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2977
2978 // Touch down on the right window
2979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2980 .deviceId(touchDeviceId)
2981 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2982 .build());
2983 leftWindow->assertNoEvents();
2984 rightWindow->consumeMotionEvent(
2985 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2986 spyWindow->consumeMotionEvent(
2987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2988
2989 // Stylus movements continue. They should be delivered to the left window and to the spy window
2990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2991 .deviceId(stylusDeviceId)
2992 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2993 .build());
2994 leftWindow->consumeMotionEvent(
2995 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2996 spyWindow->consumeMotionEvent(
2997 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2998
2999 // Further touch MOVE events keep going to the right window and to the spy
3000 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3001 .deviceId(touchDeviceId)
3002 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3003 .build());
3004 rightWindow->consumeMotionEvent(
3005 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3006 spyWindow->consumeMotionEvent(
3007 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3008
3009 spyWindow->assertNoEvents();
3010 leftWindow->assertNoEvents();
3011 rightWindow->assertNoEvents();
3012}
3013
3014/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003015 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3016 * both.
3017 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003018 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003019 * At the same time, left and right should be getting independent streams of hovering and touch,
3020 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003021 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003022TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003023 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3025
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003026 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3027 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003028 spyWindow->setFrame(Rect(0, 0, 400, 400));
3029 spyWindow->setTrustedOverlay(true);
3030 spyWindow->setSpy(true);
3031
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003032 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3033 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003034 leftWindow->setFrame(Rect(0, 0, 200, 200));
3035
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003036 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3037 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003038 rightWindow->setFrame(Rect(200, 0, 400, 200));
3039
3040 mDispatcher->onWindowInfosChanged(
3041 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3042
3043 const int32_t stylusDeviceId = 1;
3044 const int32_t touchDeviceId = 2;
3045
3046 // Stylus hover on the left window
3047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3048 .deviceId(stylusDeviceId)
3049 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3050 .build());
3051 leftWindow->consumeMotionEvent(
3052 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3053 spyWindow->consumeMotionEvent(
3054 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3055
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003056 // Touch down on the right window. Spy doesn't receive this touch because it already has
3057 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3059 .deviceId(touchDeviceId)
3060 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3061 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003062 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003063 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 rightWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3066
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003067 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3069 .deviceId(stylusDeviceId)
3070 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3071 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003072 leftWindow->consumeMotionEvent(
3073 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003074 spyWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003076
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3079 .deviceId(touchDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3081 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003082 rightWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3084
3085 spyWindow->assertNoEvents();
3086 leftWindow->assertNoEvents();
3087 rightWindow->assertNoEvents();
3088}
3089
3090/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003091 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3092 * both.
3093 * Check hover in left window and touch down in the right window.
3094 * At first, spy should receive hover. Next, spy should receive touch.
3095 * At the same time, left and right should be getting independent streams of hovering and touch,
3096 * respectively.
3097 */
3098TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3099 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3101
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003102 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3103 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003104 spyWindow->setFrame(Rect(0, 0, 400, 400));
3105 spyWindow->setTrustedOverlay(true);
3106 spyWindow->setSpy(true);
3107
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003108 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3109 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003110 leftWindow->setFrame(Rect(0, 0, 200, 200));
3111
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003112 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3113 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003114 rightWindow->setFrame(Rect(200, 0, 400, 200));
3115
3116 mDispatcher->onWindowInfosChanged(
3117 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3118
3119 const int32_t stylusDeviceId = 1;
3120 const int32_t touchDeviceId = 2;
3121
3122 // Stylus hover on the left window
3123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3124 .deviceId(stylusDeviceId)
3125 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3126 .build());
3127 leftWindow->consumeMotionEvent(
3128 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3129 spyWindow->consumeMotionEvent(
3130 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3131
3132 // Touch down on the right window.
3133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3134 .deviceId(touchDeviceId)
3135 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3136 .build());
3137 leftWindow->assertNoEvents();
3138 spyWindow->consumeMotionEvent(
3139 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3140 rightWindow->consumeMotionEvent(
3141 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3142
3143 // Stylus movements continue. They should be delivered to the left window and the spy.
3144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3145 .deviceId(stylusDeviceId)
3146 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3147 .build());
3148 leftWindow->consumeMotionEvent(
3149 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3150 spyWindow->consumeMotionEvent(
3151 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3152
3153 // Touch movements continue. They should be delivered to the right window and the spy
3154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3155 .deviceId(touchDeviceId)
3156 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3157 .build());
3158 rightWindow->consumeMotionEvent(
3159 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3160 spyWindow->consumeMotionEvent(
3161 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3162
3163 spyWindow->assertNoEvents();
3164 leftWindow->assertNoEvents();
3165 rightWindow->assertNoEvents();
3166}
3167
3168/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003169 * On a single window, use two different devices: mouse and touch.
3170 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3171 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3172 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3173 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3174 * represent a new gesture.
3175 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003176TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3177 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003179 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3180 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003181 window->setFrame(Rect(0, 0, 400, 400));
3182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003183 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003184
3185 const int32_t touchDeviceId = 4;
3186 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003187
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003188 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003193 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003194 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3195 .deviceId(touchDeviceId)
3196 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3197 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3198 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003200 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3201 .deviceId(touchDeviceId)
3202 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3203 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3204 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003205 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3206 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3207 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3208
3209 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3211 .deviceId(mouseDeviceId)
3212 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3213 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3214 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003215
3216 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003217 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003218 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3219
Prabir Pradhan678438e2023-04-13 19:32:51 +00003220 mDispatcher->notifyMotion(
3221 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3222 .deviceId(mouseDeviceId)
3223 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3224 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3225 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3226 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003227 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3228
3229 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003230 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3231 .deviceId(touchDeviceId)
3232 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3233 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3234 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003235 // Since we already canceled this touch gesture, it will be ignored until a completely new
3236 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3237 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3238 // However, mouse movements should continue to work.
3239 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3240 .deviceId(mouseDeviceId)
3241 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3243 .build());
3244 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3245
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003246 window->assertNoEvents();
3247}
3248
3249/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003250 * On a single window, use two different devices: mouse and touch.
3251 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3252 * Mouse is clicked next, which should not interfere with the touch stream.
3253 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3254 * delivered correctly.
3255 */
3256TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3257 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003259 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3260 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003261 window->setFrame(Rect(0, 0, 400, 400));
3262
3263 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3264
3265 const int32_t touchDeviceId = 4;
3266 const int32_t mouseDeviceId = 6;
3267
3268 // First touch pointer down
3269 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
3271 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3272 .build());
3273 // Second touch pointer down
3274 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3275 .deviceId(touchDeviceId)
3276 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3277 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3278 .build());
3279 // First touch pointer lifts. The second one remains down
3280 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3281 .deviceId(touchDeviceId)
3282 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3283 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3284 .build());
3285 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3286 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3287 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3288
3289 // Mouse down
3290 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3291 .deviceId(mouseDeviceId)
3292 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3294 .build());
3295
3296 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3297
3298 mDispatcher->notifyMotion(
3299 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3300 .deviceId(mouseDeviceId)
3301 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3302 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3303 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3304 .build());
3305 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3306
3307 // Second touch pointer down.
3308 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3309 .deviceId(touchDeviceId)
3310 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3311 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3312 .build());
3313 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3314 WithPointerCount(2u)));
3315
3316 // Mouse movements should continue to work
3317 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3318 .deviceId(mouseDeviceId)
3319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3321 .build());
3322 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3323
3324 window->assertNoEvents();
3325}
3326
3327/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003328 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3329 * the injected event.
3330 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003331TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3332 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003334 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3335 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003336 window->setFrame(Rect(0, 0, 400, 400));
3337
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003338 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003339
3340 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003341 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3342 // completion.
3343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003344 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003345 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3346 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003348 .build()));
3349 window->consumeMotionEvent(
3350 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3351
3352 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3353 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3355 .deviceId(touchDeviceId)
3356 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3357 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003358
3359 window->consumeMotionEvent(
3360 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3361 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3362}
3363
3364/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003365 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3366 * parallel to the injected event.
3367 */
3368TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3369 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003371 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3372 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003373 window->setFrame(Rect(0, 0, 400, 400));
3374
3375 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3376
3377 const int32_t touchDeviceId = 4;
3378 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3379 // completion.
3380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3381 injectMotionEvent(*mDispatcher,
3382 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3383 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3384 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3385 .build()));
3386 window->consumeMotionEvent(
3387 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3388
3389 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3390 // allowed through.
3391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3392 .deviceId(touchDeviceId)
3393 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3394 .build());
3395 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3396}
3397
3398/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003399 * This test is similar to the test above, but the sequence of injected events is different.
3400 *
3401 * Two windows: a window on the left and a window on the right.
3402 * Mouse is hovered over the left window.
3403 * Next, we tap on the left window, where the cursor was last seen.
3404 *
3405 * After that, we inject one finger down onto the right window, and then a second finger down onto
3406 * the left window.
3407 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3408 * window (first), and then another on the left window (second).
3409 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3410 * In the buggy implementation, second finger down on the left window would cause a crash.
3411 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003412TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3413 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003415 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3416 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003417 leftWindow->setFrame(Rect(0, 0, 200, 200));
3418
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003419 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3420 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003421 rightWindow->setFrame(Rect(200, 0, 400, 200));
3422
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003423 mDispatcher->onWindowInfosChanged(
3424 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003425
3426 const int32_t mouseDeviceId = 6;
3427 const int32_t touchDeviceId = 4;
3428 // Hover over the left window. Keep the cursor there.
3429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003430 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003431 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3432 AINPUT_SOURCE_MOUSE)
3433 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003434 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003435 .build()));
3436 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3437
3438 // Tap on left window
3439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003440 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003441 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3442 AINPUT_SOURCE_TOUCHSCREEN)
3443 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003444 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003445 .build()));
3446
3447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003448 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003449 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3450 AINPUT_SOURCE_TOUCHSCREEN)
3451 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003452 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003453 .build()));
3454 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3455 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3456 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3457
3458 // First finger down on right window
3459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003460 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003461 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3462 AINPUT_SOURCE_TOUCHSCREEN)
3463 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003464 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003465 .build()));
3466 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3467
3468 // Second finger down on the left window
3469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003470 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003471 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3472 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003473 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3474 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003475 .build()));
3476 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3477 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3478
3479 // No more events
3480 leftWindow->assertNoEvents();
3481 rightWindow->assertNoEvents();
3482}
3483
3484/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003485 * This test is similar to the test above, but the sequence of injected events is different.
3486 *
3487 * Two windows: a window on the left and a window on the right.
3488 * Mouse is hovered over the left window.
3489 * Next, we tap on the left window, where the cursor was last seen.
3490 *
3491 * After that, we send one finger down onto the right window, and then a second finger down onto
3492 * the left window.
3493 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3494 * window (first), and then another on the left window (second).
3495 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3496 * In the buggy implementation, second finger down on the left window would cause a crash.
3497 */
3498TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3499 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003501 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3502 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003503 leftWindow->setFrame(Rect(0, 0, 200, 200));
3504
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003505 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3506 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003507 rightWindow->setFrame(Rect(200, 0, 400, 200));
3508
3509 mDispatcher->onWindowInfosChanged(
3510 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3511
3512 const int32_t mouseDeviceId = 6;
3513 const int32_t touchDeviceId = 4;
3514 // Hover over the left window. Keep the cursor there.
3515 mDispatcher->notifyMotion(
3516 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3517 .deviceId(mouseDeviceId)
3518 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3519 .build());
3520 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3521
3522 // Tap on left window
3523 mDispatcher->notifyMotion(
3524 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3525 .deviceId(touchDeviceId)
3526 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3527 .build());
3528
3529 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3530 .deviceId(touchDeviceId)
3531 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3532 .build());
3533 leftWindow->consumeMotionEvent(
3534 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3535 leftWindow->consumeMotionEvent(
3536 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3537
3538 // First finger down on right window
3539 mDispatcher->notifyMotion(
3540 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3541 .deviceId(touchDeviceId)
3542 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3543 .build());
3544 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3545
3546 // Second finger down on the left window
3547 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3548 .deviceId(touchDeviceId)
3549 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3550 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3551 .build());
3552 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3553 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3554
3555 // No more events
3556 leftWindow->assertNoEvents();
3557 rightWindow->assertNoEvents();
3558}
3559
3560/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003561 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3562 * While the touch is down, new hover events from the stylus device should be ignored. After the
3563 * touch is gone, stylus hovering should start working again.
3564 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003565TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003566 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003568 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3569 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003570 window->setFrame(Rect(0, 0, 200, 200));
3571
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003573
3574 const int32_t stylusDeviceId = 5;
3575 const int32_t touchDeviceId = 4;
3576 // Start hovering with stylus
3577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003578 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003579 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003580 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003581 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003582 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003583 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003584
3585 // Finger down on the window
3586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003587 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003588 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003589 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003590 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003591 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003592 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003593
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003594 // Continue hovering with stylus.
3595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003596 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003597 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3598 AINPUT_SOURCE_STYLUS)
3599 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003600 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003601 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003602 // Hovers continue to work
3603 window->consumeMotionEvent(
3604 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003605
3606 // Lift up the finger
3607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003608 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003609 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3610 AINPUT_SOURCE_TOUCHSCREEN)
3611 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003612 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003613 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003614
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003616 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003617 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3618 AINPUT_SOURCE_STYLUS)
3619 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003620 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003621 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003622 window->consumeMotionEvent(
3623 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003624 window->assertNoEvents();
3625}
3626
3627/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003628 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3629 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3630 * check that the stylus hovering continues to work.
3631 */
3632TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3633 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003635 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3636 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003637 window->setFrame(Rect(0, 0, 200, 200));
3638
3639 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3640
3641 const int32_t stylusDeviceId = 5;
3642 const int32_t touchDeviceId = 4;
3643 // Start hovering with stylus
3644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3645 .deviceId(stylusDeviceId)
3646 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3647 .build());
3648 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3649
3650 // Finger down on the window
3651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3652 .deviceId(touchDeviceId)
3653 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3654 .build());
3655 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3656
3657 // Continue hovering with stylus.
3658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3659 .deviceId(stylusDeviceId)
3660 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3661 .build());
3662 // Hovers continue to work
3663 window->consumeMotionEvent(
3664 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3665
3666 // Lift up the finger
3667 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3668 .deviceId(touchDeviceId)
3669 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3670 .build());
3671 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3672
3673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3674 .deviceId(stylusDeviceId)
3675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3676 .build());
3677 window->consumeMotionEvent(
3678 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3679 window->assertNoEvents();
3680}
3681
3682/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003683 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3684 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3685 *
3686 * Two windows: one on the left and one on the right.
3687 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3688 * Stylus down on the left window, and then touch down on the right window.
3689 * Check that the right window doesn't get touches while the stylus is down on the left window.
3690 */
3691TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3693 sp<FakeWindowHandle> leftWindow =
3694 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003695 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003696 leftWindow->setFrame(Rect(0, 0, 100, 100));
3697
3698 sp<FakeWindowHandle> sbtRightWindow =
3699 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003700 "Stylus blocks touch (right) window",
3701 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003702 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3703 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3704
3705 mDispatcher->onWindowInfosChanged(
3706 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3707
3708 const int32_t stylusDeviceId = 5;
3709 const int32_t touchDeviceId = 4;
3710
3711 // Stylus down in the left window
3712 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3713 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3714 .deviceId(stylusDeviceId)
3715 .build());
3716 leftWindow->consumeMotionEvent(
3717 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3718
3719 // Finger tap on the right window
3720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3721 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3722 .deviceId(touchDeviceId)
3723 .build());
3724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3725 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3726 .deviceId(touchDeviceId)
3727 .build());
3728
3729 // The touch should be blocked, because stylus is down somewhere else on screen!
3730 sbtRightWindow->assertNoEvents();
3731
3732 // Continue stylus motion, and ensure it's not impacted.
3733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3734 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3735 .deviceId(stylusDeviceId)
3736 .build());
3737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3739 .deviceId(stylusDeviceId)
3740 .build());
3741 leftWindow->consumeMotionEvent(
3742 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3743 leftWindow->consumeMotionEvent(
3744 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3745
3746 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3748 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3749 .deviceId(touchDeviceId)
3750 .build());
3751 sbtRightWindow->consumeMotionEvent(
3752 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3753}
3754
3755/**
3756 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3757 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3758 *
3759 * Two windows: one on the left and one on the right.
3760 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3761 * Stylus hover on the left window, and then touch down on the right window.
3762 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3763 */
3764TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3766 sp<FakeWindowHandle> leftWindow =
3767 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003768 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003769 leftWindow->setFrame(Rect(0, 0, 100, 100));
3770
3771 sp<FakeWindowHandle> sbtRightWindow =
3772 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003773 "Stylus blocks touch (right) window",
3774 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003775 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3776 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3777
3778 mDispatcher->onWindowInfosChanged(
3779 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3780
3781 const int32_t stylusDeviceId = 5;
3782 const int32_t touchDeviceId = 4;
3783
3784 // Stylus hover in the left window
3785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3787 .deviceId(stylusDeviceId)
3788 .build());
3789 leftWindow->consumeMotionEvent(
3790 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3791
3792 // Finger tap on the right window
3793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3794 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3795 .deviceId(touchDeviceId)
3796 .build());
3797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3798 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3799 .deviceId(touchDeviceId)
3800 .build());
3801
3802 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3803 sbtRightWindow->assertNoEvents();
3804
3805 // Continue stylus motion, and ensure it's not impacted.
3806 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3807 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3808 .deviceId(stylusDeviceId)
3809 .build());
3810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3811 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3812 .deviceId(stylusDeviceId)
3813 .build());
3814 leftWindow->consumeMotionEvent(
3815 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3816 leftWindow->consumeMotionEvent(
3817 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3818
3819 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3821 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3822 .deviceId(touchDeviceId)
3823 .build());
3824 sbtRightWindow->consumeMotionEvent(
3825 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3826}
3827
3828/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003829 * A spy window above a window with no input channel.
3830 * Start hovering with a stylus device, and then tap with it.
3831 * Ensure spy window receives the entire sequence.
3832 */
3833TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003835 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3836 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003837 spyWindow->setFrame(Rect(0, 0, 200, 200));
3838 spyWindow->setTrustedOverlay(true);
3839 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003840 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3841 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003842 window->setNoInputChannel(true);
3843 window->setFrame(Rect(0, 0, 200, 200));
3844
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003845 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003846
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003847 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003848 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3849 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3850 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003851 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3852 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3855 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003856 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3857
3858 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3860 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3861 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003862 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3863
3864 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3866 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3867 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003868 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3869
3870 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3872 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3873 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003874 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3875 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3877 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003879 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3880
3881 // No more events
3882 spyWindow->assertNoEvents();
3883 window->assertNoEvents();
3884}
3885
3886/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003887 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3888 * rejected. But since we already have an ongoing gesture, this event should be processed.
3889 * This prevents inconsistent events being handled inside the dispatcher.
3890 */
3891TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3893
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003894 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3895 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003896 window->setFrame(Rect(0, 0, 200, 200));
3897
3898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3899
3900 // Start hovering with stylus
3901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3902 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3903 .build());
3904 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3905
3906 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3907 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3908 .build();
3909 // Make this 'hoverExit' event stale
3910 mFakePolicy->setStaleEventTimeout(100ms);
3911 std::this_thread::sleep_for(100ms);
3912
3913 // It shouldn't be dropped by the dispatcher, even though it's stale.
3914 mDispatcher->notifyMotion(hoverExit);
3915 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3916
3917 // Stylus starts hovering again! There should be no crash.
3918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3919 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3920 .build());
3921 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3922}
3923
3924/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003925 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3926 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3927 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3928 * While the mouse is down, new move events from the touch device should be ignored.
3929 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003930TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3931 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003932 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003933 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3934 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 spyWindow->setFrame(Rect(0, 0, 200, 200));
3936 spyWindow->setTrustedOverlay(true);
3937 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3939 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003940 window->setFrame(Rect(0, 0, 200, 200));
3941
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003942 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003943
3944 const int32_t mouseDeviceId = 7;
3945 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003946
3947 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003948 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3949 .deviceId(mouseDeviceId)
3950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3951 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003952 spyWindow->consumeMotionEvent(
3953 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3954 window->consumeMotionEvent(
3955 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3956
3957 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3959 .deviceId(touchDeviceId)
3960 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3961 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003962 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3963 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3964 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3965 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3966
Prabir Pradhan678438e2023-04-13 19:32:51 +00003967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3968 .deviceId(touchDeviceId)
3969 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3970 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003971 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3972 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3973
3974 // Pilfer the stream
3975 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3976 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3977
Prabir Pradhan678438e2023-04-13 19:32:51 +00003978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3979 .deviceId(touchDeviceId)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3981 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003982 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3983
3984 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3986 .deviceId(mouseDeviceId)
3987 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3988 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3989 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003990
3991 spyWindow->consumeMotionEvent(
3992 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3993 spyWindow->consumeMotionEvent(
3994 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3996
Prabir Pradhan678438e2023-04-13 19:32:51 +00003997 mDispatcher->notifyMotion(
3998 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3999 .deviceId(mouseDeviceId)
4000 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4001 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4003 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004004 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4005 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4006
4007 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00004008 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4009 .deviceId(mouseDeviceId)
4010 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4011 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4012 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004013 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4014 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4015
4016 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00004017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4018 .deviceId(touchDeviceId)
4019 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4020 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004021
4022 // No more events
4023 spyWindow->assertNoEvents();
4024 window->assertNoEvents();
4025}
4026
4027/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004028 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
4029 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
4030 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
4031 * While the mouse is down, new move events from the touch device should continue to work.
4032 */
4033TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
4034 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004036 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4037 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004038 spyWindow->setFrame(Rect(0, 0, 200, 200));
4039 spyWindow->setTrustedOverlay(true);
4040 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004041 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4042 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004043 window->setFrame(Rect(0, 0, 200, 200));
4044
4045 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4046
4047 const int32_t mouseDeviceId = 7;
4048 const int32_t touchDeviceId = 4;
4049
4050 // Hover a bit with mouse first
4051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4052 .deviceId(mouseDeviceId)
4053 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4054 .build());
4055 spyWindow->consumeMotionEvent(
4056 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4057 window->consumeMotionEvent(
4058 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4059
4060 // Start touching
4061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4062 .deviceId(touchDeviceId)
4063 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4064 .build());
4065
4066 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4067 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4068
4069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4070 .deviceId(touchDeviceId)
4071 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
4072 .build());
4073 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4074 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4075
4076 // Pilfer the stream
4077 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4078 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
4079 // Hover is not pilfered! Only touch.
4080
4081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4082 .deviceId(touchDeviceId)
4083 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
4084 .build());
4085 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4086
4087 // Mouse down
4088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4089 .deviceId(mouseDeviceId)
4090 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4091 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4092 .build());
4093
4094 spyWindow->consumeMotionEvent(
4095 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4096 spyWindow->consumeMotionEvent(
4097 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4098 window->consumeMotionEvent(
4099 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4100 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4101
4102 mDispatcher->notifyMotion(
4103 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4104 .deviceId(mouseDeviceId)
4105 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4106 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4107 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4108 .build());
4109 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4110 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4111
4112 // Mouse move!
4113 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4114 .deviceId(mouseDeviceId)
4115 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4116 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4117 .build());
4118 spyWindow->consumeMotionEvent(
4119 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4120 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4121
4122 // Touch move!
4123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4124 .deviceId(touchDeviceId)
4125 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4126 .build());
4127 spyWindow->consumeMotionEvent(
4128 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4129
4130 // No more events
4131 spyWindow->assertNoEvents();
4132 window->assertNoEvents();
4133}
4134
4135/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004136 * On the display, have a single window, and also an area where there's no window.
4137 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4138 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4139 */
4140TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4142 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004143 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004144
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004145 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004146
4147 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004148 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004149
4150 mDispatcher->waitForIdle();
4151 window->assertNoEvents();
4152
4153 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004154 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004155 mDispatcher->waitForIdle();
4156 window->consumeMotionDown();
4157}
4158
4159/**
4160 * Same test as above, but instead of touching the empty space, the first touch goes to
4161 * non-touchable window.
4162 */
4163TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4165 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004166 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004167 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4168 window1->setTouchable(false);
4169 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004171 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4172
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004173 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004174
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004175 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004176 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004177
4178 mDispatcher->waitForIdle();
4179 window1->assertNoEvents();
4180 window2->assertNoEvents();
4181
4182 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004183 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004184 mDispatcher->waitForIdle();
4185 window2->consumeMotionDown();
4186}
4187
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004188/**
4189 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4190 * to the event time of the first ACTION_DOWN sent to the particular window.
4191 */
4192TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4194 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004195 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004196 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4197 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004198 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004199 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4200
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004201 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004202
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004203 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004204 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004205 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004206
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004207 const std::unique_ptr<MotionEvent> firstDown =
4208 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4209 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004210 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004211
4212 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004213 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004214 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004215
4216 const std::unique_ptr<MotionEvent> secondDown =
4217 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4218 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4219 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4220 // We currently send MOVE events to all windows receiving a split touch when there is any change
4221 // in the touch state, even when none of the pointers in the split window actually moved.
4222 // Document this behavior in the test.
4223 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004224
4225 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004226 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004227 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004228
4229 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4230 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004231
4232 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004233 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004234 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004235
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004236 window2->consumeMotionEvent(
4237 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4238 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004239
4240 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004241 mDispatcher->notifyMotion(
4242 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004243 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004244
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004245 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4246 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4247
4248 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004249 mDispatcher->notifyMotion(
4250 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004251 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004252
4253 window1->consumeMotionEvent(
4254 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4255 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004256}
4257
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004258/**
4259 * When events are not split, the downTime should be adjusted such that the downTime corresponds
4260 * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
4261 * the event routing because the first window prevents splitting.
4262 */
4263TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004264 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4266 sp<FakeWindowHandle> window1 =
4267 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4268 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4269 window1->setPreventSplitting(true);
4270
4271 sp<FakeWindowHandle> window2 =
4272 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4273 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4274
4275 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4276
4277 // Touch down on the first window
4278 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4279 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4280 .build();
4281 mDispatcher->notifyMotion(downArgs);
4282
4283 window1->consumeMotionEvent(
4284 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4285
4286 // Second window is added
4287 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4288
4289 // Now touch down on the window with another pointer
4290 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4291 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4292 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4293 .downTime(downArgs.downTime)
4294 .build());
4295 window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4296
4297 // Finish the gesture
4298 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4299 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4300 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4301 .downTime(downArgs.downTime)
4302 .build());
4303 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4304 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4305 .downTime(downArgs.downTime)
4306 .build());
4307 window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4308 window1->consumeMotionEvent(
4309 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4310 window2->assertNoEvents();
4311}
4312
4313/**
4314 * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4315 * to the event time of the first ACTION_DOWN sent to the new window.
4316 * If a new window that does not support split appears on the screen and gets touched with the
4317 * second finger, it should not get any events because it doesn't want split touches. At the same
4318 * time, the first window should not get the pointer_down event because it supports split touches
4319 * (and the touch occurred outside of the bounds of window1).
4320 */
4321TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004322 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4324 sp<FakeWindowHandle> window1 =
4325 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4326 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4327
4328 sp<FakeWindowHandle> window2 =
4329 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4330 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4331
4332 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4333
4334 // Touch down on the first window
4335 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4336 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4337 .build();
4338 mDispatcher->notifyMotion(downArgs);
4339
4340 window1->consumeMotionEvent(
4341 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4342
4343 // Second window is added
4344 window2->setPreventSplitting(true);
4345 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4346
4347 // Now touch down on the window with another pointer
4348 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4349 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4350 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4351 .downTime(downArgs.downTime)
4352 .build());
4353 // Event is dropped because window2 doesn't support split touch, and window1 does.
4354
4355 // Complete the gesture
4356 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4357 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4358 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4359 .downTime(downArgs.downTime)
4360 .build());
4361 // A redundant MOVE event is generated that doesn't carry any new information
4362 window1->consumeMotionEvent(
4363 AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4365 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4366 .downTime(downArgs.downTime)
4367 .build());
4368
4369 window1->consumeMotionEvent(
4370 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4371 window1->assertNoEvents();
4372 window2->assertNoEvents();
4373}
4374
Garfield Tandf26e862020-07-01 20:18:19 -07004375TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004377 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4378 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004379 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004380 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4381 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004382 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004383
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004384 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004385
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004386 mDispatcher->onWindowInfosChanged(
4387 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004388
4389 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004391 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004392 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4393 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004394 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004395 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004396 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004397
4398 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004400 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004401 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4402 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004404 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004405 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4406 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004407
4408 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004410 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004411 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4412 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004414 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004415 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4416 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004417
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004419 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004420 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4421 AINPUT_SOURCE_MOUSE)
4422 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4423 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004424 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004425 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004426 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004427
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004429 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004430 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4431 AINPUT_SOURCE_MOUSE)
4432 .buttonState(0)
4433 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004434 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004435 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004436 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004437
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004439 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004440 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4441 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004442 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004443 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004444 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004445
4446 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004448 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004449 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4450 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004451 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004452 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004453 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004454
4455 // No more events
4456 windowLeft->assertNoEvents();
4457 windowRight->assertNoEvents();
4458}
4459
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004460/**
4461 * Put two fingers down (and don't release them) and click the mouse button.
4462 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4463 * currently active gesture should be canceled, and the new one should proceed.
4464 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004465TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4466 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004468 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4469 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004470 window->setFrame(Rect(0, 0, 600, 800));
4471
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004472 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004473
4474 const int32_t touchDeviceId = 4;
4475 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004476
4477 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004478 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4479 .deviceId(touchDeviceId)
4480 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004482
Prabir Pradhan678438e2023-04-13 19:32:51 +00004483 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4484 .deviceId(touchDeviceId)
4485 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4486 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4487 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004488 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4489 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4490
4491 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4493 .deviceId(mouseDeviceId)
4494 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4495 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4496 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004497 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4498 WithPointerCount(2u)));
4499 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4500
Prabir Pradhan678438e2023-04-13 19:32:51 +00004501 mDispatcher->notifyMotion(
4502 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4503 .deviceId(mouseDeviceId)
4504 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4505 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4506 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4507 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004508 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4509
4510 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4511 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4513 .deviceId(touchDeviceId)
4514 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4515 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4516 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004517 window->assertNoEvents();
4518}
4519
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004520/**
4521 * Put two fingers down (and don't release them) and click the mouse button.
4522 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4523 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4524 */
4525TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4526 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004528 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4529 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004530 window->setFrame(Rect(0, 0, 600, 800));
4531
4532 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4533
4534 const int32_t touchDeviceId = 4;
4535 const int32_t mouseDeviceId = 6;
4536
4537 // Two pointers down
4538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4539 .deviceId(touchDeviceId)
4540 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4541 .build());
4542
4543 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4544 .deviceId(touchDeviceId)
4545 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4546 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4547 .build());
4548 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4549 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4550
4551 // Send a series of mouse events for a mouse click
4552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4553 .deviceId(mouseDeviceId)
4554 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4555 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4556 .build());
4557 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4558
4559 mDispatcher->notifyMotion(
4560 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4561 .deviceId(mouseDeviceId)
4562 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4563 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4564 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4565 .build());
4566 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4567
4568 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4569 // already active gesture, it should be sent normally.
4570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4571 .deviceId(touchDeviceId)
4572 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4573 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4574 .build());
4575 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4576 window->assertNoEvents();
4577}
4578
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004579/**
4580 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4581 * though the window underneath should not get any events.
4582 */
4583TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
4584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4585
4586 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4587 ui::LogicalDisplayId::DEFAULT);
4588 spyWindow->setFrame(Rect(0, 0, 100, 100));
4589 spyWindow->setTrustedOverlay(true);
4590 spyWindow->setPreventSplitting(true);
4591 spyWindow->setSpy(true);
4592 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4593 sp<FakeWindowHandle> inputSinkWindow =
4594 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4595 ui::LogicalDisplayId::DEFAULT);
4596 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4597 inputSinkWindow->setTrustedOverlay(true);
4598 inputSinkWindow->setPreventSplitting(true);
4599 inputSinkWindow->setNoInputChannel(true);
4600
4601 mDispatcher->onWindowInfosChanged(
4602 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4603
4604 // Tap the spy window
4605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4606 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4607 .build());
4608 mDispatcher->notifyMotion(
4609 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4610 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4611 .build());
4612
4613 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4614 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4615 inputSinkWindow->assertNoEvents();
4616}
4617
4618/**
4619 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4620 * though the window underneath should not get any events.
4621 * Same test as above, but with two pointers touching instead of one.
4622 */
4623TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
4624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4625
4626 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4627 ui::LogicalDisplayId::DEFAULT);
4628 spyWindow->setFrame(Rect(0, 0, 100, 100));
4629 spyWindow->setTrustedOverlay(true);
4630 spyWindow->setPreventSplitting(true);
4631 spyWindow->setSpy(true);
4632 // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4633 sp<FakeWindowHandle> inputSinkWindow =
4634 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4635 ui::LogicalDisplayId::DEFAULT);
4636 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4637 inputSinkWindow->setTrustedOverlay(true);
4638 inputSinkWindow->setPreventSplitting(true);
4639 inputSinkWindow->setNoInputChannel(true);
4640
4641 mDispatcher->onWindowInfosChanged(
4642 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4643
4644 // Both fingers land into the spy window
4645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4646 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4647 .build());
4648 mDispatcher->notifyMotion(
4649 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4650 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4651 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4652 .build());
4653 mDispatcher->notifyMotion(
4654 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4655 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4656 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4657 .build());
4658 mDispatcher->notifyMotion(
4659 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4660 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4661 .build());
4662
4663 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4664 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4665 spyWindow->consumeMotionPointerUp(1, WithPointerCount(2));
4666 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4667 inputSinkWindow->assertNoEvents();
4668}
4669
4670/** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
4671class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
4672 public ::testing::WithParamInterface<bool> {
4673};
4674
4675/**
4676 * Three windows:
4677 * - An application window (app window)
4678 * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
4679 * - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
4680 *
4681 * The spy window is side-by-side with the app window. The inputSink is below the spy.
4682 * We first touch the area outside of the appWindow, but inside spyWindow.
4683 * Only the SPY window should get the DOWN event.
4684 * The spy pilfers after receiving the first DOWN event.
4685 * Next, we touch the app window.
4686 * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
4687 * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
4688 * pointers automatically, as well.
4689 * Next, the first pointer (from the spy) is lifted.
4690 * Spy should get POINTER_UP(0).
4691 * This event should not go to the app because the app never received this pointer to begin with.
4692 * Now, lift the remaining pointer and check that the spy receives UP event.
4693 *
4694 * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
4695 * This test attempts to reproduce a crash in the dispatcher.
4696 */
4697TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004698 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4700
4701 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4702 ui::LogicalDisplayId::DEFAULT);
4703 spyWindow->setFrame(Rect(100, 100, 200, 200));
4704 spyWindow->setTrustedOverlay(true);
4705 spyWindow->setPreventSplitting(true);
4706 spyWindow->setSpy(true);
4707 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4708 sp<FakeWindowHandle> inputSinkWindow =
4709 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4710 ui::LogicalDisplayId::DEFAULT);
4711 inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
4712 inputSinkWindow->setTrustedOverlay(true);
4713 inputSinkWindow->setPreventSplitting(GetParam());
4714 inputSinkWindow->setNoInputChannel(true);
4715
4716 sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
4717 ui::LogicalDisplayId::DEFAULT);
4718 appWindow->setFrame(Rect(0, 0, 100, 100));
4719
4720 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4721 mDispatcher->onWindowInfosChanged(
4722 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo(), *appWindow->getInfo()},
4723 {},
4724 0,
4725 0});
4726
4727 // First finger lands outside of the appWindow, but inside of the spy window
4728 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4729 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4730 .build());
4731 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4732
4733 mDispatcher->pilferPointers(spyWindow->getToken());
4734
4735 // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
4736 // the spy is already pilfering the first pointer, and this automatically grants the remaining
4737 // new pointers to the spy, as well.
4738 mDispatcher->notifyMotion(
4739 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4740 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4741 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4742 .build());
4743
4744 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4745
4746 // Now lift up the first pointer
4747 mDispatcher->notifyMotion(
4748 MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
4749 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4750 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4751 .build());
4752 spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
4753
4754 // And lift the remaining pointer!
4755 mDispatcher->notifyMotion(
4756 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4757 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4758 .build());
4759 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
4760
4761 // Now send a new DOWN, which should again go to spy.
4762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4764 .build());
4765 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4766 // The app window doesn't get any events this entire time because the spy received the events
4767 // first and pilfered, which makes all new pointers go to it as well.
4768 appWindow->assertNoEvents();
4769}
4770
4771// Behaviour should be the same regardless of whether inputSink supports splitting.
4772INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
4773 SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
4774
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004775TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4777
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004778 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4779 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004780 spyWindow->setFrame(Rect(0, 0, 600, 800));
4781 spyWindow->setTrustedOverlay(true);
4782 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004783 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4784 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004785 window->setFrame(Rect(0, 0, 600, 800));
4786
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004787 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004788 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004789
4790 // Send mouse cursor to the window
4791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004792 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004793 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4794 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004795 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004796 .build()));
4797
4798 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4799 WithSource(AINPUT_SOURCE_MOUSE)));
4800 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4801 WithSource(AINPUT_SOURCE_MOUSE)));
4802
4803 window->assertNoEvents();
4804 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004805}
4806
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004807TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4808 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4810
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004811 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4812 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004813 spyWindow->setFrame(Rect(0, 0, 600, 800));
4814 spyWindow->setTrustedOverlay(true);
4815 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004816 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4817 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004818 window->setFrame(Rect(0, 0, 600, 800));
4819
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004820 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004821 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004822
4823 // Send mouse cursor to the window
4824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004825 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004826 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4827 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004829 .build()));
4830
4831 // Move mouse cursor
4832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004833 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004834 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4835 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004836 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004837 .build()));
4838
4839 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4840 WithSource(AINPUT_SOURCE_MOUSE)));
4841 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4842 WithSource(AINPUT_SOURCE_MOUSE)));
4843 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4844 WithSource(AINPUT_SOURCE_MOUSE)));
4845 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4846 WithSource(AINPUT_SOURCE_MOUSE)));
4847 // Touch down on the window
4848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004849 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004850 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4851 AINPUT_SOURCE_TOUCHSCREEN)
4852 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004853 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004854 .build()));
4855 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4856 WithSource(AINPUT_SOURCE_MOUSE)));
4857 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4858 WithSource(AINPUT_SOURCE_MOUSE)));
4859 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4860 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4861 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4862 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4863
4864 // pilfer the motion, retaining the gesture on the spy window.
4865 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4866 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4867 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4868
4869 // Touch UP on the window
4870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004871 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004872 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4873 AINPUT_SOURCE_TOUCHSCREEN)
4874 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004875 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004876 .build()));
4877 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4878 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4879
4880 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4881 // to send a new gesture. It should again go to both windows (spy and the window below), just
4882 // like the first gesture did, before pilfering. The window configuration has not changed.
4883
4884 // One more tap - DOWN
4885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004886 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004887 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4888 AINPUT_SOURCE_TOUCHSCREEN)
4889 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004890 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004891 .build()));
4892 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4893 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4894 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4895 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4896
4897 // Touch UP on the window
4898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004899 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004900 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4901 AINPUT_SOURCE_TOUCHSCREEN)
4902 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004903 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004904 .build()));
4905 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4906 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4907 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4908 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4909
4910 window->assertNoEvents();
4911 spyWindow->assertNoEvents();
4912}
4913
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004914TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4915 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4917
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004918 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4919 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004920 spyWindow->setFrame(Rect(0, 0, 600, 800));
4921 spyWindow->setTrustedOverlay(true);
4922 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004923 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4924 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004925 window->setFrame(Rect(0, 0, 600, 800));
4926
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004927 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004928 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4929
4930 // Send mouse cursor to the window
4931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4932 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4933 .build());
4934
4935 // Move mouse cursor
4936 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4937 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4938 .build());
4939
4940 window->consumeMotionEvent(
4941 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4942 spyWindow->consumeMotionEvent(
4943 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4944 window->consumeMotionEvent(
4945 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4946 spyWindow->consumeMotionEvent(
4947 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4948 // Touch down on the window
4949 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4950 .deviceId(SECOND_DEVICE_ID)
4951 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4952 .build());
4953 window->consumeMotionEvent(
4954 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4955 spyWindow->consumeMotionEvent(
4956 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4957
4958 // pilfer the motion, retaining the gesture on the spy window.
4959 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4960 window->consumeMotionEvent(
4961 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4962 // Mouse hover is not pilfered
4963
4964 // Touch UP on the window
4965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4966 .deviceId(SECOND_DEVICE_ID)
4967 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4968 .build());
4969 spyWindow->consumeMotionEvent(
4970 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4971
4972 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4973 // to send a new gesture. It should again go to both windows (spy and the window below), just
4974 // like the first gesture did, before pilfering. The window configuration has not changed.
4975
4976 // One more tap - DOWN
4977 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4978 .deviceId(SECOND_DEVICE_ID)
4979 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4980 .build());
4981 window->consumeMotionEvent(
4982 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4983 spyWindow->consumeMotionEvent(
4984 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4985
4986 // Touch UP on the window
4987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4988 .deviceId(SECOND_DEVICE_ID)
4989 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4990 .build());
4991 window->consumeMotionEvent(
4992 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4993 spyWindow->consumeMotionEvent(
4994 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4995
4996 // Mouse movement continues normally as well
4997 // Move mouse cursor
4998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
5000 .build());
5001 window->consumeMotionEvent(
5002 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
5003 spyWindow->consumeMotionEvent(
5004 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
5005
5006 window->assertNoEvents();
5007 spyWindow->assertNoEvents();
5008}
5009
Garfield Tandf26e862020-07-01 20:18:19 -07005010// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
5011// directly in this test.
5012TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07005013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005014 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5015 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07005016 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07005017
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005018 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07005019
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005020 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07005021
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005023 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005024 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5025 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005026 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005027 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005028 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07005029 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005031 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005032 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5033 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005034 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005035 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08005036 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5037 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07005038
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005040 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005041 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
5042 AINPUT_SOURCE_MOUSE)
5043 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
5044 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005045 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005046 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005047 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07005048
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005050 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005051 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
5052 AINPUT_SOURCE_MOUSE)
5053 .buttonState(0)
5054 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005055 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005056 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005057 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07005058
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005060 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005061 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
5062 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005063 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005064 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005065 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07005066
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07005067 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
5068 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
5069 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005070 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005071 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
5072 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005073 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005074 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08005075 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07005076}
5077
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005078/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005079 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
5080 * is generated.
5081 */
5082TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
5083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005084 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5085 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005086 window->setFrame(Rect(0, 0, 1200, 800));
5087
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005088 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005090 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005091
5092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005093 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005094 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5095 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005096 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005097 .build()));
5098 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5099
5100 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005101 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005102 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
5103}
5104
5105/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07005106 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
5107 */
Siarhei Vishniakou67b101b2024-10-12 00:42:44 +00005108TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07005109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005110 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5111 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005112 window->setFrame(Rect(0, 0, 1200, 800));
5113
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005114 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005115
5116 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5117
5118 MotionEventBuilder hoverEnterBuilder =
5119 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5121 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5123 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
Siarhei Vishniakou67b101b2024-10-12 00:42:44 +00005124 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5125 // Another HOVER_ENTER would be inconsistent, and should therefore fail to
5126 // get injected.
5127 ASSERT_EQ(InputEventInjectionResult::FAILED,
Daniel Norman7487dfa2023-08-02 16:39:45 -07005128 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
Daniel Norman7487dfa2023-08-02 16:39:45 -07005129}
5130
5131/**
Siarhei Vishniakou9d0d65e2024-08-02 12:10:05 -07005132 * Invalid events injected by input filter are rejected.
5133 */
5134TEST_F(InputDispatcherTest, InvalidA11yEventsGetRejected) {
5135 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5136 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5137 ui::LogicalDisplayId::DEFAULT);
5138
5139 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5140
5141 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5142
5143 // a11y sets 'POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY' policy flag during injection, so define
5144 // a custom injection function here for convenience.
5145 auto injectFromAccessibility = [&](int32_t action, float x, float y) {
5146 MotionEvent event = MotionEventBuilder(action, AINPUT_SOURCE_TOUCHSCREEN)
5147 .pointer(PointerBuilder(0, ToolType::FINGER).x(x).y(y))
5148 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT)
5149 .build();
5150 return injectMotionEvent(*mDispatcher, event, 100ms,
5151 InputEventInjectionSync::WAIT_FOR_RESULT, /*targetUid=*/{},
5152 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_FILTERED |
5153 POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY);
5154 };
5155
5156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5157 injectFromAccessibility(ACTION_DOWN, /*x=*/300, /*y=*/400));
5158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5159 injectFromAccessibility(ACTION_MOVE, /*x=*/310, /*y=*/420));
5160 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5161 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5162 // finger is still down, so a new DOWN event should be rejected!
5163 ASSERT_EQ(InputEventInjectionResult::FAILED,
5164 injectFromAccessibility(ACTION_DOWN, /*x=*/340, /*y=*/410));
5165
5166 // if the gesture is correctly finished, new down event will succeed
5167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5168 injectFromAccessibility(ACTION_MOVE, /*x=*/320, /*y=*/430));
5169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5170 injectFromAccessibility(ACTION_UP, /*x=*/320, /*y=*/430));
5171 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5172 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5173
5174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5175 injectFromAccessibility(ACTION_DOWN, /*x=*/350, /*y=*/460));
5176 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5177}
5178
5179/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005180 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
5181 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005182TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
5183 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005184 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005185 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5186 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005187 window->setFrame(Rect(0, 0, 100, 100));
5188
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005189 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005190
5191 const int32_t mouseDeviceId = 7;
5192 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005193
5194 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00005195 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5196 .deviceId(mouseDeviceId)
5197 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5198 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005199 window->consumeMotionEvent(
5200 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5201
5202 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00005203 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5204 .deviceId(touchDeviceId)
5205 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5206 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005207
5208 window->consumeMotionEvent(
5209 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
5210 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5211}
5212
5213/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005214 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
5215 */
5216TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
5217 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5218 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005219 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5220 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005221 window->setFrame(Rect(0, 0, 100, 100));
5222
5223 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5224
5225 const int32_t mouseDeviceId = 7;
5226 const int32_t touchDeviceId = 4;
5227
5228 // Start hovering with the mouse
5229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5230 .deviceId(mouseDeviceId)
5231 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5232 .build());
5233 window->consumeMotionEvent(
5234 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5235
5236 // Touch goes down
5237 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5238 .deviceId(touchDeviceId)
5239 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5240 .build());
5241 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5242}
5243
5244/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005245 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005246 * The tap causes a HOVER_EXIT event to be generated because the current event
5247 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005248 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005249TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
5250 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005251 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005252 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5253 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005254 window->setFrame(Rect(0, 0, 100, 100));
5255
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005256 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5258 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5259 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005260 ASSERT_NO_FATAL_FAILURE(
5261 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5262 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005263
5264 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5266 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5267 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005268 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005269 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5270 WithSource(AINPUT_SOURCE_MOUSE))));
5271
5272 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005273 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5274 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5275
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5277 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5278 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005279 ASSERT_NO_FATAL_FAILURE(
5280 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5281 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5282}
5283
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005284/**
5285 * Send a mouse hover event followed by a tap from touchscreen.
5286 * The tap causes a HOVER_EXIT event to be generated because the current event
5287 * stream's source has been switched.
5288 */
5289TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
5290 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5291 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005292 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5293 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005294 window->setFrame(Rect(0, 0, 100, 100));
5295
5296 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5297 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5298 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5299 .build());
5300
5301 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5302 WithSource(AINPUT_SOURCE_MOUSE)));
5303
5304 // Tap on the window
5305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5306 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5307 .build());
5308
5309 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5310 WithSource(AINPUT_SOURCE_MOUSE)));
5311
5312 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5313 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5314
5315 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5316 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5317 .build());
5318
5319 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5320 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5321}
5322
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005323TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
5324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5325 sp<FakeWindowHandle> windowDefaultDisplay =
5326 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005327 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005328 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
5329 sp<FakeWindowHandle> windowSecondDisplay =
5330 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
5331 SECOND_DISPLAY_ID);
5332 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
5333
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005334 mDispatcher->onWindowInfosChanged(
5335 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005336
5337 // Set cursor position in window in default display and check that hover enter and move
5338 // events are generated.
5339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005340 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005341 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5342 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005343 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005344 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005345 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005346 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005347
5348 // Remove all windows in secondary display and check that no event happens on window in
5349 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005350 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5351
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005352 windowDefaultDisplay->assertNoEvents();
5353
5354 // Move cursor position in window in default display and check that only hover move
5355 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005356 mDispatcher->onWindowInfosChanged(
5357 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005359 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005360 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5361 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005362 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005363 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005364 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005365 windowDefaultDisplay->consumeMotionEvent(
5366 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5367 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005368 windowDefaultDisplay->assertNoEvents();
5369}
5370
Garfield Tan00f511d2019-06-12 16:55:40 -07005371TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005373
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005374 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5375 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005376 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005377 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5378 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005379 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005380
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005381 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005382
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005383 mDispatcher->onWindowInfosChanged(
5384 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005385
5386 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5387 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005389 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005390 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5391 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005392 windowRight->assertNoEvents();
5393}
5394
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005395TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005397 sp<FakeWindowHandle> window =
5398 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5399 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005400 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005403 setFocusedWindow(window);
5404
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005405 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005406
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005407 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005408
5409 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005410 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005411
5412 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5413 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005414 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005415 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005416}
5417
5418TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005419 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005420 sp<FakeWindowHandle> window =
5421 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5422 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005423
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005424 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005425
Prabir Pradhan678438e2023-04-13 19:32:51 +00005426 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005427 AINPUT_SOURCE_TOUCHSCREEN,
5428 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005429
5430 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005431 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005432
5433 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5434 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005435 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005436 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005437 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005438}
5439
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005440TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5441 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005442 sp<FakeWindowHandle> window =
5443 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5444 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005445
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005446 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005447
5448 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5449 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5450 .build());
5451
5452 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5453
5454 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5455 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5456 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5457
5458 // After the device has been reset, a new hovering stream can be sent to the window
5459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5460 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5461 .build());
5462 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5463}
5464
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005465TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005467 sp<FakeWindowHandle> window =
5468 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5469 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005470 window->setFocusable(true);
5471
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005472 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005473 setFocusedWindow(window);
5474
5475 window->consumeFocusEvent(true);
5476
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005477 const NotifyKeyArgs keyArgs =
5478 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005479 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5480 const nsecs_t injectTime = keyArgs.eventTime;
5481 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005482 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005483 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005484 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005485 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5486 std::chrono::nanoseconds(interceptKeyTimeout).count());
5487}
5488
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005489/**
5490 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5491 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005492TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005494 sp<FakeWindowHandle> window =
5495 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5496 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005497 window->setFocusable(true);
5498
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005500 setFocusedWindow(window);
5501
5502 window->consumeFocusEvent(true);
5503
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005504 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5505 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005506
5507 // Set a value that's significantly larger than the default consumption timeout. If the
5508 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5509 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005510 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005511 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005512 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005513}
5514
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005515/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005516 * Two windows. First is a regular window. Second does not overlap with the first, and has
5517 * WATCH_OUTSIDE_TOUCH.
5518 * Both windows are owned by the same UID.
5519 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5520 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5521 */
5522TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005524 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5525 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005526 window->setFrame(Rect{0, 0, 100, 100});
5527
5528 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005529 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005530 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005531 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5532 outsideWindow->setWatchOutsideTouch(true);
5533 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005534 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005535
5536 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005538 AINPUT_SOURCE_TOUCHSCREEN,
5539 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005540 window->consumeMotionDown();
5541 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5542 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5543 outsideWindow->consumeMotionEvent(
5544 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005545
5546 // Ensure outsideWindow doesn't get any more events for the gesture.
5547 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005548 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005549 window->consumeMotionMove();
5550 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005551}
5552
5553/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005554 * Three windows:
5555 * - Left window
5556 * - Right window
5557 * - Outside window(watch for ACTION_OUTSIDE events)
5558 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5559 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5560 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5561 *
5562 * First, device A report a down event landed in the right window, the outside window can receive
5563 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5564 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5565 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5566 * window can receive it, but outside window event can't receive it.
5567 */
5568TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5570 sp<FakeWindowHandle> leftWindow =
5571 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005572 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005573 leftWindow->setFrame(Rect{0, 0, 100, 100});
5574 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5575
5576 sp<FakeWindowHandle> outsideWindow =
5577 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005578 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005579 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5580 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5581 outsideWindow->setWatchOutsideTouch(true);
5582
5583 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5584 std::make_shared<FakeApplicationHandle>();
5585 sp<FakeWindowHandle> rightWindow =
5586 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005587 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005588 rightWindow->setFrame(Rect{100, 0, 200, 100});
5589 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5590
5591 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5592 // when left window or right window is tapped
5593 mDispatcher->onWindowInfosChanged(
5594 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5595 {},
5596 0,
5597 0});
5598
5599 const DeviceId deviceA = 9;
5600 const DeviceId deviceB = 3;
5601
5602 // Tap on right window use device A
5603 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5604 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5605 .deviceId(deviceA)
5606 .build());
5607 leftWindow->assertNoEvents();
5608 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5609 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5610 // with zeroed coords.
5611 outsideWindow->consumeMotionEvent(
5612 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5613
5614 // Tap on left window use device B
5615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5616 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5617 .deviceId(deviceB)
5618 .build());
5619 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5620 rightWindow->assertNoEvents();
5621 // Because new gesture down on the left window that has the same owner with outside Window, the
5622 // outside Window should receive the ACTION_OUTSIDE with coords.
5623 outsideWindow->consumeMotionEvent(
5624 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5625
5626 // Ensure that windows that can only accept outside do not receive remaining gestures
5627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5628 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5629 .deviceId(deviceA)
5630 .build());
5631 leftWindow->assertNoEvents();
5632 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5633
5634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5635 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5636 .deviceId(deviceB)
5637 .build());
5638 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5639 rightWindow->assertNoEvents();
5640 outsideWindow->assertNoEvents();
5641}
5642
5643/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005644 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5645 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5646 * ACTION_OUTSIDE event is sent per gesture.
5647 */
5648TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5649 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005651 sp<FakeWindowHandle> window =
5652 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5653 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005654 window->setWatchOutsideTouch(true);
5655 window->setFrame(Rect{0, 0, 100, 100});
5656 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005657 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005658 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005659 secondWindow->setFrame(Rect{100, 100, 200, 200});
5660 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005661 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005662 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005663 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005664 mDispatcher->onWindowInfosChanged(
5665 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005666
5667 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005668 mDispatcher->notifyMotion(
5669 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5670 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005671 window->assertNoEvents();
5672 secondWindow->assertNoEvents();
5673
5674 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5675 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005676 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005677 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005678 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005679 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5680 window->consumeMotionEvent(
5681 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005682 secondWindow->consumeMotionDown();
5683 thirdWindow->assertNoEvents();
5684
5685 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5686 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005687 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005688 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5689 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005690 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005691 window->assertNoEvents();
5692 secondWindow->consumeMotionMove();
5693 thirdWindow->consumeMotionDown();
5694}
5695
Prabir Pradhan814fe082022-07-22 20:22:18 +00005696TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005698 sp<FakeWindowHandle> window =
5699 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5700 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005701 window->setFocusable(true);
5702
Patrick Williamsd828f302023-04-28 17:52:08 -05005703 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005704 setFocusedWindow(window);
5705
5706 window->consumeFocusEvent(true);
5707
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005708 const NotifyKeyArgs keyDown =
5709 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5710 const NotifyKeyArgs keyUp =
5711 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005712 mDispatcher->notifyKey(keyDown);
5713 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005714
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005715 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5716 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005717
5718 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005719 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005720
5721 window->consumeFocusEvent(false);
5722
Prabir Pradhan678438e2023-04-13 19:32:51 +00005723 mDispatcher->notifyKey(keyDown);
5724 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005725 window->assertNoEvents();
5726}
5727
Arthur Hung96483742022-11-15 03:30:48 +00005728TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005729 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Arthur Hung96483742022-11-15 03:30:48 +00005730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005731 sp<FakeWindowHandle> window =
5732 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5733 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005734 // Ensure window is non-split and have some transform.
5735 window->setPreventSplitting(true);
5736 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005738
5739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005740 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5741 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005743 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005744
5745 const MotionEvent secondFingerDownEvent =
5746 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005747 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005748 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005749 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5750 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005751 .build();
5752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005753 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005754 InputEventInjectionSync::WAIT_FOR_RESULT))
5755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5756
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005757 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5758 ASSERT_NE(nullptr, event);
5759 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5760 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5761 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5762 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5763 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005764}
5765
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005766/**
5767 * Two windows: a splittable and a non-splittable.
5768 * The non-splittable window shouldn't receive any "incomplete" gestures.
5769 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5770 * The second pointer should be dropped because the initial window is splittable, so it won't get
5771 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5772 * "incomplete" gestures.
5773 */
5774TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005775 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5777 sp<FakeWindowHandle> leftWindow =
5778 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005779 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005780 leftWindow->setPreventSplitting(false);
5781 leftWindow->setFrame(Rect(0, 0, 100, 100));
5782 sp<FakeWindowHandle> rightWindow =
5783 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005784 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005785 rightWindow->setPreventSplitting(true);
5786 rightWindow->setFrame(Rect(100, 100, 200, 200));
5787 mDispatcher->onWindowInfosChanged(
5788 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5789
5790 // Touch down on left, splittable window
5791 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5792 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5793 .build());
5794 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5795
5796 mDispatcher->notifyMotion(
5797 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5798 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5799 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5800 .build());
5801 leftWindow->assertNoEvents();
5802 rightWindow->assertNoEvents();
5803}
5804
Siarhei Vishniakou96204462024-07-13 23:59:47 -07005805/**
Siarhei Vishniakoufe346982024-08-07 00:17:19 +00005806 * Three windows:
5807 * 1) A window on the left, with flag dup_to_wallpaper
5808 * 2) A window on the right, with flag slippery
5809 * 3) A wallpaper window under the left window
5810 * When touch slips from right window to left, the wallpaper should receive a similar slippery
5811 * enter event. Later on, when another device becomes active, the wallpaper should receive
5812 * consistent streams from the new device, and also from the old device.
5813 * This test attempts to reproduce a crash in the dispatcher where the wallpaper target's downTime
5814 * was not getting set during slippery entrance.
5815 */
5816TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch) {
5817 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5818 std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5819 std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5820 std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5821 sp<FakeWindowHandle> wallpaper =
5822 sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5823 ui::LogicalDisplayId::DEFAULT);
5824 wallpaper->setIsWallpaper(true);
5825 wallpaper->setPreventSplitting(true);
5826 wallpaper->setTouchable(false);
5827
5828 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5829 ui::LogicalDisplayId::DEFAULT);
5830 leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5831 leftWindow->setDupTouchToWallpaper(true);
5832
5833 sp<FakeWindowHandle> rightWindow =
5834 sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5835 ui::LogicalDisplayId::DEFAULT);
5836 rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5837 rightWindow->setSlippery(true);
5838 rightWindow->setWatchOutsideTouch(true);
5839 rightWindow->setTrustedOverlay(true);
5840
5841 mDispatcher->onWindowInfosChanged(
5842 {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5843
5844 const DeviceId deviceA = 3;
5845 const DeviceId deviceB = 9;
5846
5847 // First finger from device A into right window
5848 NotifyMotionArgs deviceADownArgs =
5849 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5850 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5851 .deviceId(deviceA)
5852 .build();
5853
5854 mDispatcher->notifyMotion(deviceADownArgs);
5855 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5856
5857 // Move the finger of device A from right window into left window. It should slip.
5858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5859 .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5860 .deviceId(deviceA)
5861 .downTime(deviceADownArgs.downTime)
5862 .build());
5863
5864 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5865 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
5866 wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5867
5868 // Finger from device B down into left window
5869 NotifyMotionArgs deviceBDownArgs =
5870 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5871 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5872 .deviceId(deviceB)
5873 .build();
5874 mDispatcher->notifyMotion(deviceBDownArgs);
5875 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5876 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5877
5878 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
5879
5880 // Move finger from device B, still keeping it in the left window
5881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5882 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5883 .deviceId(deviceB)
5884 .downTime(deviceBDownArgs.downTime)
5885 .build());
5886 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5887 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5888
5889 // Lift the finger from device B
5890 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5891 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5892 .deviceId(deviceB)
5893 .downTime(deviceBDownArgs.downTime)
5894 .build());
5895 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5896 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5897
5898 // Move the finger of device A, keeping it in the left window
5899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5900 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5901 .deviceId(deviceA)
5902 .downTime(deviceADownArgs.downTime)
5903 .build());
5904
5905 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5906 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5907
5908 // Second finger down from device A, into the right window. It should be split into:
5909 // MOVE for the left window (due to existing implementation) + a DOWN into the right window
5910 // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
5911 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5912 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5913 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5914 .deviceId(deviceA)
5915 .downTime(deviceADownArgs.downTime)
5916 .build());
5917 auto firstFingerMoveFromDeviceA = AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE),
5918 WithPointerCount(1), WithPointerId(0, 0));
5919 leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5920 wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5921 rightWindow->consumeMotionEvent(
5922 AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
5923
5924 // Lift up the second finger.
5925 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5926 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5927 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5928 .deviceId(deviceA)
5929 .downTime(deviceADownArgs.downTime)
5930 .build());
5931
5932 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5933 leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5934 wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5935
5936 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5937 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5938 .deviceId(deviceA)
5939 .downTime(deviceADownArgs.downTime)
5940 .build());
5941
5942 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5943 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5944 rightWindow->assertNoEvents();
5945}
5946
5947/**
5948 * Same test as above, but with enable_multi_device_same_window_stream flag set to false.
5949 */
5950TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch_legacy) {
5951 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
5952 std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5953 std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5954 std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5955 sp<FakeWindowHandle> wallpaper =
5956 sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5957 ui::LogicalDisplayId::DEFAULT);
5958 wallpaper->setIsWallpaper(true);
5959 wallpaper->setPreventSplitting(true);
5960 wallpaper->setTouchable(false);
5961
5962 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5963 ui::LogicalDisplayId::DEFAULT);
5964 leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5965 leftWindow->setDupTouchToWallpaper(true);
5966
5967 sp<FakeWindowHandle> rightWindow =
5968 sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5969 ui::LogicalDisplayId::DEFAULT);
5970 rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5971 rightWindow->setSlippery(true);
5972 rightWindow->setWatchOutsideTouch(true);
5973 rightWindow->setTrustedOverlay(true);
5974
5975 mDispatcher->onWindowInfosChanged(
5976 {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5977
5978 const DeviceId deviceA = 3;
5979 const DeviceId deviceB = 9;
5980
5981 // First finger from device A into right window
5982 NotifyMotionArgs deviceADownArgs =
5983 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5984 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5985 .deviceId(deviceA)
5986 .build();
5987
5988 mDispatcher->notifyMotion(deviceADownArgs);
5989 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5990
5991 // Move the finger of device A from right window into left window. It should slip.
5992 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5993 .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5994 .deviceId(deviceA)
5995 .downTime(deviceADownArgs.downTime)
5996 .build());
5997
5998 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5999 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6000 wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6001
6002 // Finger from device B down into left window
6003 NotifyMotionArgs deviceBDownArgs =
6004 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6005 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6006 .deviceId(deviceB)
6007 .build();
6008 mDispatcher->notifyMotion(deviceBDownArgs);
6009 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
6010 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
6011 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
6012 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
6013
6014 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
6015
6016 // Move finger from device B, still keeping it in the left window
6017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6018 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
6019 .deviceId(deviceB)
6020 .downTime(deviceBDownArgs.downTime)
6021 .build());
6022 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
6023 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
6024
6025 // Lift the finger from device B
6026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6027 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
6028 .deviceId(deviceB)
6029 .downTime(deviceBDownArgs.downTime)
6030 .build());
6031 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
6032 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
6033
6034 // Move the finger of device A, keeping it in the left window
6035 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6036 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6037 .deviceId(deviceA)
6038 .downTime(deviceADownArgs.downTime)
6039 .build());
6040 // This device was already canceled, so MOVE events will not be arriving to the windows from it.
6041
6042 // Second finger down from device A, into the right window. It should be split into:
6043 // MOVE for the left window (due to existing implementation) + a DOWN into the right window
6044 // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
6045 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6046 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6047 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
6048 .deviceId(deviceA)
6049 .downTime(deviceADownArgs.downTime)
6050 .build());
6051 rightWindow->consumeMotionEvent(
6052 AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
6053
6054 // Lift up the second finger.
6055 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6056 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6057 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
6058 .deviceId(deviceA)
6059 .downTime(deviceADownArgs.downTime)
6060 .build());
6061
6062 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
6063
6064 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6065 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6066 .deviceId(deviceA)
6067 .downTime(deviceADownArgs.downTime)
6068 .build());
6069 rightWindow->assertNoEvents();
6070}
6071
6072/**
Siarhei Vishniakou96204462024-07-13 23:59:47 -07006073 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
6074 * down event to the right window. Device B sends a down event to the left window, and then a
6075 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
6076 * POINTER_DOWN event should only go to the left window, and not to the right window.
6077 * This test attempts to reproduce a crash.
6078 */
6079TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07006080 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou96204462024-07-13 23:59:47 -07006081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6082 sp<FakeWindowHandle> leftWindow =
6083 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
6084 ui::LogicalDisplayId::DEFAULT);
6085 leftWindow->setFrame(Rect(0, 0, 100, 100));
6086 leftWindow->setPreventSplitting(true);
6087
6088 sp<FakeWindowHandle> rightWindow =
6089 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
6090 ui::LogicalDisplayId::DEFAULT);
6091 rightWindow->setFrame(Rect(100, 0, 200, 100));
6092
6093 mDispatcher->onWindowInfosChanged(
6094 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
6095
6096 const DeviceId deviceA = 9;
6097 const DeviceId deviceB = 3;
6098 // Touch the right window with device A
6099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6100 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6101 .deviceId(deviceA)
6102 .build());
6103 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
6104 // Touch the left window with device B
6105 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6106 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6107 .deviceId(deviceB)
6108 .build());
6109 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
6110 // Send a second pointer from device B to the right window. It shouldn't go to the right window
6111 // because the left window prevents splitting.
6112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6113 .deviceId(deviceB)
6114 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6115 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6116 .build());
6117 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
6118
6119 // Finish the gesture for both devices
6120 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6121 .deviceId(deviceB)
6122 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6123 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6124 .build());
6125 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
6126 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6127 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6128 .deviceId(deviceB)
6129 .build());
6130 leftWindow->consumeMotionEvent(
6131 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
6132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6133 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6134 .deviceId(deviceA)
6135 .build());
6136 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
6137}
6138
Harry Cuttsb166c002023-05-09 13:06:05 +00006139TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
6140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006141 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6142 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006143 window->setFrame(Rect(0, 0, 400, 400));
6144 sp<FakeWindowHandle> trustedOverlay =
6145 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006146 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006147 trustedOverlay->setSpy(true);
6148 trustedOverlay->setTrustedOverlay(true);
6149
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006150 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00006151
6152 // Start a three-finger touchpad swipe
6153 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6154 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6155 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6156 .build());
6157 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6158 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6159 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6160 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6161 .build());
6162 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6163 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6164 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6165 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6166 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6167 .build());
6168
6169 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6170 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6171 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
6172
6173 // Move the swipe a bit
6174 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6175 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6176 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6177 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6178 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6179 .build());
6180
6181 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6182
6183 // End the swipe
6184 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6185 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6186 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6187 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6188 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6189 .build());
6190 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6191 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6192 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6193 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6194 .build());
6195 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6196 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6197 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6198 .build());
6199
6200 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
6201 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6202 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
6203
6204 window->assertNoEvents();
6205}
6206
6207TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
6208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006209 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6210 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006211 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006212 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00006213
6214 // Start a three-finger touchpad swipe
6215 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6216 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6217 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6218 .build());
6219 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6220 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6221 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6222 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6223 .build());
6224 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6225 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6226 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6227 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6228 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6229 .build());
6230
6231 // Move the swipe a bit
6232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6233 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6234 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6235 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6236 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6237 .build());
6238
6239 // End the swipe
6240 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6241 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6242 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6243 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6244 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6245 .build());
6246 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6247 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6248 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6249 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6250 .build());
6251 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6252 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6253 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6254 .build());
6255
6256 window->assertNoEvents();
6257}
6258
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00006259/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006260 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
6261 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006262 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006263 */
6264TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
6265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006266 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6267 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006268 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006269 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006270
6271 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
6272 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6273 .downTime(baseTime + 10)
6274 .eventTime(baseTime + 10)
6275 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6276 .build());
6277
6278 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6279
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006280 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006281 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006282
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006283 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006284
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006285 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6286 .downTime(baseTime + 10)
6287 .eventTime(baseTime + 30)
6288 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6289 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6290 .build());
6291
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006292 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6293
6294 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006295 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6296 .downTime(baseTime + 10)
6297 .eventTime(baseTime + 40)
6298 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6299 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6300 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006301
6302 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6303
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006304 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6305 .downTime(baseTime + 10)
6306 .eventTime(baseTime + 50)
6307 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6308 .build());
6309
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006310 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
6311
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6313 .downTime(baseTime + 60)
6314 .eventTime(baseTime + 60)
6315 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6316 .build());
6317
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006318 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006319}
6320
6321/**
Hu Guo771a7692023-09-17 20:51:08 +08006322 * When there are multiple screens, such as screen projection to TV or screen recording, if the
6323 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
6324 * its coordinates should be converted by the transform of the windows of target screen.
6325 */
6326TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
6327 // This case will create a window and a spy window on the default display and mirror
6328 // window on the second display. cancel event is sent through spy window pilferPointers
6329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6330
6331 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006332 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6333 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08006334 spyWindowDefaultDisplay->setTrustedOverlay(true);
6335 spyWindowDefaultDisplay->setSpy(true);
6336
6337 sp<FakeWindowHandle> windowDefaultDisplay =
6338 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006339 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08006340 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
6341
6342 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
6343 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
6344
6345 // Add the windows to the dispatcher
6346 mDispatcher->onWindowInfosChanged(
6347 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
6348 *windowSecondDisplay->getInfo()},
6349 {},
6350 0,
6351 0});
6352
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006353 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08006354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006355 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6356 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08006357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6358
6359 spyWindowDefaultDisplay->consumeMotionDown();
6360 windowDefaultDisplay->consumeMotionDown();
6361
6362 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
6363
6364 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006365 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
6366 ASSERT_NE(nullptr, event);
6367 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08006368
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006369 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
6370 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
6371 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
6372 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006373 EXPECT_EQ(100, event->getX(0));
6374 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08006375}
6376
6377/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006378 * Ensure the correct coordinate spaces are used by InputDispatcher.
6379 *
6380 * InputDispatcher works in the display space, so its coordinate system is relative to the display
6381 * panel. Windows get events in the window space, and get raw coordinates in the logical display
6382 * space.
6383 */
6384class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
6385public:
6386 void SetUp() override {
6387 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006388 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006389 }
6390
Linnan Li13bf76a2024-05-05 19:18:02 +08006391 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006392 gui::DisplayInfo info;
6393 info.displayId = displayId;
6394 info.transform = transform;
6395 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05006396 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006397 }
6398
6399 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
6400 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05006401 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006402 }
6403
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006404 void removeAllWindowsAndDisplays() {
6405 mDisplayInfos.clear();
6406 mWindowInfos.clear();
6407 }
6408
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006409 // Set up a test scenario where the display has a scaled projection and there are two windows
6410 // on the display.
6411 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
6412 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
6413 // respectively.
6414 ui::Transform displayTransform;
6415 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006416 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006417
6418 std::shared_ptr<FakeApplicationHandle> application =
6419 std::make_shared<FakeApplicationHandle>();
6420
6421 // Add two windows to the display. Their frames are represented in the display space.
6422 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006423 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006424 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006425 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
6426 addWindow(firstWindow);
6427
6428 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006429 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006430 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006431 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
6432 addWindow(secondWindow);
6433 return {std::move(firstWindow), std::move(secondWindow)};
6434 }
6435
6436private:
6437 std::vector<gui::DisplayInfo> mDisplayInfos;
6438 std::vector<gui::WindowInfo> mWindowInfos;
6439};
6440
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006441TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006442 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6443 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006444 // selected so that if the hit test was performed with the point and the bounds being in
6445 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006446 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006447 AINPUT_SOURCE_TOUCHSCREEN,
6448 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006449
6450 firstWindow->consumeMotionDown();
6451 secondWindow->assertNoEvents();
6452}
6453
6454// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
6455// the event should be treated as being in the logical display space.
6456TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
6457 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6458 // Send down to the first window. The point is represented in the logical display space. The
6459 // point is selected so that if the hit test was done in logical display space, then it would
6460 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006461 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006462 PointF{75 * 2, 55 * 4});
6463
6464 firstWindow->consumeMotionDown();
6465 secondWindow->assertNoEvents();
6466}
6467
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006468// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
6469// event should be treated as being in the logical display space.
6470TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
6471 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6472
6473 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6474 ui::Transform injectedEventTransform;
6475 injectedEventTransform.set(matrix);
6476 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
6477 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
6478
6479 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006480 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006481 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006482 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006483 .x(untransformedPoint.x)
6484 .y(untransformedPoint.y))
6485 .build();
6486 event.transform(matrix);
6487
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006488 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006489 InputEventInjectionSync::WAIT_FOR_RESULT);
6490
6491 firstWindow->consumeMotionDown();
6492 secondWindow->assertNoEvents();
6493}
6494
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006495TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
6496 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6497
6498 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006499 mDispatcher->notifyMotion(
6500 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6501 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006502
6503 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006504 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
6505 ASSERT_NE(nullptr, event);
6506 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006507
6508 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006509 EXPECT_EQ(300, event->getRawX(0));
6510 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006511
6512 // Ensure that the x and y values are in the window's coordinate space.
6513 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
6514 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006515 EXPECT_EQ(100, event->getX(0));
6516 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006517}
6518
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006519TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
6520 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6521 // The monitor will always receive events in the logical display's coordinate space, because
6522 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006523 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006524
6525 // Send down to the first window.
6526 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006527 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006528 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6529 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6530
6531 // Second pointer goes down on second window.
6532 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006533 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006534 {PointF{50, 100}, PointF{150, 220}}));
6535 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
6536 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
6537 {1, PointF{300, 880}}};
6538 monitor.consumeMotionEvent(
6539 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
6540
6541 mDispatcher->cancelCurrentTouch();
6542
6543 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6544 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
6545 monitor.consumeMotionEvent(
6546 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
6547}
6548
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006549TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
6550 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6551
6552 // Send down to the first window.
6553 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006554 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006555 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6556
6557 // The pointer is transferred to the second window, and the second window receives it in the
6558 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006559 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006560 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6561 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
6562}
6563
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006564TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
6565 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6566
6567 // Send hover move to the second window, and ensure it shows up as hover enter.
6568 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006569 ui::LogicalDisplayId::DEFAULT,
6570 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006571 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6572 WithCoords(100, 80), WithRawCoords(300, 880)));
6573
6574 // Touch down at the same location and ensure a hover exit is synthesized.
6575 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006576 ui::LogicalDisplayId::DEFAULT,
6577 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006578 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6579 WithRawCoords(300, 880)));
6580 secondWindow->consumeMotionEvent(
6581 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6582 secondWindow->assertNoEvents();
6583 firstWindow->assertNoEvents();
6584}
6585
Prabir Pradhan453ae732023-10-13 14:30:14 +00006586// Same as above, but while the window is being mirrored.
6587TEST_F(InputDispatcherDisplayProjectionTest,
6588 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
6589 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6590
6591 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6592 ui::Transform secondDisplayTransform;
6593 secondDisplayTransform.set(matrix);
6594 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6595
6596 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6597 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6598 addWindow(secondWindowClone);
6599
6600 // Send hover move to the second window, and ensure it shows up as hover enter.
6601 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006602 ui::LogicalDisplayId::DEFAULT,
6603 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006604 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6605 WithCoords(100, 80), WithRawCoords(300, 880)));
6606
6607 // Touch down at the same location and ensure a hover exit is synthesized for the correct
6608 // display.
6609 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006610 ui::LogicalDisplayId::DEFAULT,
6611 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006612 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6613 WithRawCoords(300, 880)));
6614 secondWindow->consumeMotionEvent(
6615 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6616 secondWindow->assertNoEvents();
6617 firstWindow->assertNoEvents();
6618}
6619
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006620TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6621 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6622
6623 // Send hover enter to second window
6624 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006625 ui::LogicalDisplayId::DEFAULT,
6626 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006627 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6628 WithCoords(100, 80), WithRawCoords(300, 880)));
6629
6630 mDispatcher->cancelCurrentTouch();
6631
6632 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6633 WithRawCoords(300, 880)));
6634 secondWindow->assertNoEvents();
6635 firstWindow->assertNoEvents();
6636}
6637
Prabir Pradhan453ae732023-10-13 14:30:14 +00006638// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00006639TEST_F(InputDispatcherDisplayProjectionTest,
6640 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6641 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6642
6643 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6644 ui::Transform secondDisplayTransform;
6645 secondDisplayTransform.set(matrix);
6646 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6647
6648 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6649 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6650 addWindow(secondWindowClone);
6651
6652 // Send hover enter to second window
6653 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006654 ui::LogicalDisplayId::DEFAULT,
6655 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00006656 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6657 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006658 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006659
6660 mDispatcher->cancelCurrentTouch();
6661
6662 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6663 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6664 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006665 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006666 secondWindow->assertNoEvents();
6667 firstWindow->assertNoEvents();
6668}
6669
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006670/** Ensure consistent behavior of InputDispatcher in all orientations. */
6671class InputDispatcherDisplayOrientationFixture
6672 : public InputDispatcherDisplayProjectionTest,
6673 public ::testing::WithParamInterface<ui::Rotation> {};
6674
6675// This test verifies the touchable region of a window for all rotations of the display by tapping
6676// in different locations on the display, specifically points close to the four corners of a
6677// window.
6678TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6679 constexpr static int32_t displayWidth = 400;
6680 constexpr static int32_t displayHeight = 800;
6681
6682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6683
6684 const auto rotation = GetParam();
6685
6686 // Set up the display with the specified rotation.
6687 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6688 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6689 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6690 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6691 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006692 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006693
6694 // Create a window with its bounds determined in the logical display.
6695 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6696 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006697 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6698 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006699 window->setFrame(frameInDisplay, displayTransform);
6700 addWindow(window);
6701
6702 // The following points in logical display space should be inside the window.
6703 static const std::array<vec2, 4> insidePoints{
6704 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6705 for (const auto pointInsideWindow : insidePoints) {
6706 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6707 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006708 mDispatcher->notifyMotion(
6709 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6710 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006711 window->consumeMotionDown();
6712
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006713 mDispatcher->notifyMotion(
6714 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6715 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006716 window->consumeMotionUp();
6717 }
6718
6719 // The following points in logical display space should be outside the window.
6720 static const std::array<vec2, 5> outsidePoints{
6721 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6722 for (const auto pointOutsideWindow : outsidePoints) {
6723 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6724 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006725 mDispatcher->notifyMotion(
6726 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6727 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006728
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006729 mDispatcher->notifyMotion(
6730 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6731 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006732 }
6733 window->assertNoEvents();
6734}
6735
Linnan Li5e5645e2024-03-05 14:43:05 +00006736// This test verifies the occlusion detection for all rotations of the display by tapping
6737// in different locations on the display, specifically points close to the four corners of a
6738// window.
6739TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6740 constexpr static int32_t displayWidth = 400;
6741 constexpr static int32_t displayHeight = 800;
6742
6743 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6744 std::make_shared<FakeApplicationHandle>();
6745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6746
6747 const auto rotation = GetParam();
6748
6749 // Set up the display with the specified rotation.
6750 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6751 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6752 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6753 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6754 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006755 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006756
6757 // Create a window that not trusted.
6758 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6759
6760 const Rect untrustedWindowFrameInDisplay =
6761 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6762
6763 sp<FakeWindowHandle> untrustedWindow =
6764 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006765 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006766 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6767 untrustedWindow->setTrustedOverlay(false);
6768 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6769 untrustedWindow->setTouchable(false);
6770 untrustedWindow->setAlpha(1.0f);
6771 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6772 addWindow(untrustedWindow);
6773
6774 // Create a simple app window below the untrusted window.
6775 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6776 const Rect simpleAppWindowFrameInDisplay =
6777 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6778
6779 sp<FakeWindowHandle> simpleAppWindow =
6780 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006781 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006782 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6783 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6784 addWindow(simpleAppWindow);
6785
6786 // The following points in logical display space should be inside the untrusted window, so
6787 // the simple window could not receive events that coordinate is these point.
6788 static const std::array<vec2, 4> untrustedPoints{
6789 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6790
6791 for (const auto untrustedPoint : untrustedPoints) {
6792 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6793 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006794 mDispatcher->notifyMotion(
6795 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6796 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6797 mDispatcher->notifyMotion(
6798 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6799 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006800 }
6801 untrustedWindow->assertNoEvents();
6802 simpleAppWindow->assertNoEvents();
6803 // The following points in logical display space should be outside the untrusted window, so
6804 // the simple window should receive events that coordinate is these point.
6805 static const std::array<vec2, 5> trustedPoints{
6806 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6807 for (const auto trustedPoint : trustedPoints) {
6808 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6809 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006810 mDispatcher->notifyMotion(
6811 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6812 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6813 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006814 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006815 mDispatcher->notifyMotion(
6816 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6817 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6818 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006819 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6820 }
6821 untrustedWindow->assertNoEvents();
6822}
6823
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006824// Run the precision tests for all rotations.
6825INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6826 InputDispatcherDisplayOrientationFixture,
6827 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6828 ui::ROTATION_270),
6829 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6830 return ftl::enum_string(testParamInfo.param);
6831 });
6832
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006833using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6834 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006835
6836class TransferTouchFixture : public InputDispatcherTest,
6837 public ::testing::WithParamInterface<TransferFunction> {};
6838
6839TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006841
6842 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006843 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006844 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006845 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006846 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006847 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006848 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006849 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006850 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006851 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6852 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006853 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006854 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006855 mDispatcher->onWindowInfosChanged(
6856 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006857 setFocusedWindow(firstWindow);
6858 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006859
6860 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006861 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006862 AINPUT_SOURCE_TOUCHSCREEN,
6863 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006864
Svet Ganov5d3bc372020-01-26 23:11:07 -08006865 // Only the first window should get the down event
6866 firstWindow->consumeMotionDown();
6867 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006868 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006869 // Dispatcher reports pointer down outside focus for the wallpaper
6870 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006871
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006872 // Transfer touch to the second window
6873 TransferFunction f = GetParam();
6874 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6875 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006876 // The first window gets cancel and the second gets down
6877 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006878 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6879 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6880 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006881 // There should not be any changes to the focused window when transferring touch
6882 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006883
6884 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006885 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006886 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006887 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006888 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006889 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6890 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006891 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006892}
6893
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006894/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006895 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6896 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6897 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006898 * natural to the user.
6899 * In this test, we are sending a pointer to both spy window and first window. We then try to
6900 * transfer touch to the second window. The dispatcher should identify the first window as the
6901 * one that should lose the gesture, and therefore the action should be to move the gesture from
6902 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006903 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6904 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006905 */
6906TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6908
6909 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006910 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6911 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006912 spyWindow->setTrustedOverlay(true);
6913 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006914 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6915 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006916 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006917 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6918 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006919
6920 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006921 mDispatcher->onWindowInfosChanged(
6922 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006923
6924 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006925 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006926 AINPUT_SOURCE_TOUCHSCREEN,
6927 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006928 // Only the first window and spy should get the down event
6929 spyWindow->consumeMotionDown();
6930 firstWindow->consumeMotionDown();
6931
6932 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006933 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006934 TransferFunction f = GetParam();
6935 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6936 ASSERT_TRUE(success);
6937 // The first window gets cancel and the second gets down
6938 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006939 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6940 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006941
6942 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006943 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006944 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006945 // The first window gets no events and the second+spy get up
6946 firstWindow->assertNoEvents();
6947 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006948 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6949 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006950}
6951
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006952TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006954
6955 PointF touchPoint = {10, 10};
6956
6957 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006958 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006959 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006960 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006961 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006962 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006963 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006964 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006965 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006966
6967 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006968 mDispatcher->onWindowInfosChanged(
6969 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006970
6971 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006972 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006973 AINPUT_SOURCE_TOUCHSCREEN,
6974 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006975 // Only the first window should get the down event
6976 firstWindow->consumeMotionDown();
6977 secondWindow->assertNoEvents();
6978
6979 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006980 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006981 ui::LogicalDisplayId::DEFAULT,
6982 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006983 // Only the first window should get the pointer down event
6984 firstWindow->consumeMotionPointerDown(1);
6985 secondWindow->assertNoEvents();
6986
6987 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006988 TransferFunction f = GetParam();
6989 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6990 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006991 // The first window gets cancel and the second gets down and pointer down
6992 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006993 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6994 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6995 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006996 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006997
6998 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006999 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007000 ui::LogicalDisplayId::DEFAULT,
7001 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007002 // The first window gets nothing and the second gets pointer up
7003 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00007004 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7005 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7006 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7007 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007008
7009 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007010 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007011 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007012 // The first window gets nothing and the second gets up
7013 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007014 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7015 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007016}
7017
Arthur Hungc539dbb2022-12-08 07:45:36 +00007018TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
7019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7020
7021 // Create a couple of windows
7022 sp<FakeWindowHandle> firstWindow =
7023 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007024 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007025 firstWindow->setDupTouchToWallpaper(true);
7026 sp<FakeWindowHandle> secondWindow =
7027 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007028 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007029 secondWindow->setDupTouchToWallpaper(true);
7030
7031 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007032 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
7033 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007034 wallpaper1->setIsWallpaper(true);
7035
7036 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007037 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
7038 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007039 wallpaper2->setIsWallpaper(true);
7040 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007041 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
7042 *secondWindow->getInfo(), *wallpaper2->getInfo()},
7043 {},
7044 0,
7045 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00007046
7047 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007048 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007049 AINPUT_SOURCE_TOUCHSCREEN,
7050 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00007051
7052 // Only the first window should get the down event
7053 firstWindow->consumeMotionDown();
7054 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007055 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007056 wallpaper2->assertNoEvents();
7057
7058 // Transfer touch focus to the second window
7059 TransferFunction f = GetParam();
7060 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
7061 ASSERT_TRUE(success);
7062
7063 // The first window gets cancel and the second gets down
7064 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007065 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
7066 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7067 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
7068 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08007069 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007070
7071 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007072 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007073 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00007074 // The first window gets no events and the second gets up
7075 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007076 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7077 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007078 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007079 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08007080 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007081}
7082
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007083// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00007084// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007085// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00007086INSTANTIATE_TEST_SUITE_P(
7087 InputDispatcherTransferFunctionTests, TransferTouchFixture,
7088 ::testing::Values(
7089 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
7090 sp<IBinder> destChannelToken) {
7091 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007092 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00007093 },
7094 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
7095 sp<IBinder> to) {
7096 return dispatcher->transferTouchGesture(from, to,
7097 /*isDragAndDrop=*/false);
7098 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007099
Prabir Pradhan367f3432024-02-13 23:05:58 +00007100TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07007101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08007102
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007103 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007104 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007105 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007106 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007107
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007108 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007109 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007110 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007111 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007112
7113 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007114 mDispatcher->onWindowInfosChanged(
7115 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08007116
7117 PointF pointInFirst = {300, 200};
7118 PointF pointInSecond = {300, 600};
7119
7120 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007121 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007122 AINPUT_SOURCE_TOUCHSCREEN,
7123 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007124 // Only the first window should get the down event
7125 firstWindow->consumeMotionDown();
7126 secondWindow->assertNoEvents();
7127
7128 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007129 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007130 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007131 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007132 // The first window gets a move and the second a down
7133 firstWindow->consumeMotionMove();
7134 secondWindow->consumeMotionDown();
7135
Prabir Pradhan367f3432024-02-13 23:05:58 +00007136 // Transfer touch to the second window
7137 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08007138 // The first window gets cancel and the new gets pointer down (it already saw down)
7139 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007140 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007141 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007142
7143 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007144 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007145 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007146 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007147 // The first window gets nothing and the second gets pointer up
7148 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00007149 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7150 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7151 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7152 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007153
7154 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007155 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007156 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007157 // The first window gets nothing and the second gets up
7158 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007159 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7160 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007161}
7162
Prabir Pradhan367f3432024-02-13 23:05:58 +00007163// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
7164// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
7165// receiving touch is not supported, so the touch should continue on those windows and the
7166// transferred-to window should get nothing.
7167TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7169
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007170 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007171 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007172 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007173 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007174
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007175 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007176 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007177 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007178 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007179
7180 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007181 mDispatcher->onWindowInfosChanged(
7182 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007183
7184 PointF pointInFirst = {300, 200};
7185 PointF pointInSecond = {300, 600};
7186
7187 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007188 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007189 AINPUT_SOURCE_TOUCHSCREEN,
7190 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007191 // Only the first window should get the down event
7192 firstWindow->consumeMotionDown();
7193 secondWindow->assertNoEvents();
7194
7195 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007196 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007197 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007198 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007199 // The first window gets a move and the second a down
7200 firstWindow->consumeMotionMove();
7201 secondWindow->consumeMotionDown();
7202
7203 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007204 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
7205 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00007206 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007207 ASSERT_FALSE(transferred);
7208 firstWindow->assertNoEvents();
7209 secondWindow->assertNoEvents();
7210
7211 // The rest of the dispatch should proceed as normal
7212 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007213 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007214 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007215 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007216 // The first window gets MOVE and the second gets pointer up
7217 firstWindow->consumeMotionMove();
7218 secondWindow->consumeMotionUp();
7219
7220 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007221 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007222 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007223 // The first window gets nothing and the second gets up
7224 firstWindow->consumeMotionUp();
7225 secondWindow->assertNoEvents();
7226}
7227
Arthur Hungabbb9d82021-09-01 14:52:30 +00007228// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00007229// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00007230// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00007231TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00007232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7233 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007234 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7235 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007236 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007237 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007238 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7239 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007240 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007241
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007242 sp<FakeWindowHandle> mirrorWindowInPrimary =
7243 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007244 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007245
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007246 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007247 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007248
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007249 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007250 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007251
7252 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007253 mDispatcher->onWindowInfosChanged(
7254 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7255 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7256 *secondWindowInPrimary->getInfo()},
7257 {},
7258 0,
7259 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00007260
7261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007262 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7263 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007264 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7265
7266 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007267 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007268
Prabir Pradhan367f3432024-02-13 23:05:58 +00007269 // Transfer touch
7270 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
7271 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007272 // The first window gets cancel.
7273 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007274 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007275 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007276
7277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007278 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007279 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007280 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7281 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007282 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007283 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007284
7285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007286 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00007287 {150, 50}))
7288 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7289 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007290 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7291 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007292}
7293
Prabir Pradhan367f3432024-02-13 23:05:58 +00007294// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
7295// 'transferTouchOnDisplay' api.
7296TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00007297 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7298 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007299 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7300 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007301 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007302 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007303 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7304 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007305 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007306
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007307 sp<FakeWindowHandle> mirrorWindowInPrimary =
7308 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007309 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007310
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007311 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007312 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007313
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007314 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007315 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007316
7317 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007318 mDispatcher->onWindowInfosChanged(
7319 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7320 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7321 *secondWindowInPrimary->getInfo()},
7322 {},
7323 0,
7324 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00007325
7326 // Touch on second display.
7327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007328 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7329 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7331
7332 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007333 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007334
7335 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00007336 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
7337 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007338
7339 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007340 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00007341 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
7342 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007343
7344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007345 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00007346 SECOND_DISPLAY_ID, {150, 50}))
7347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007348 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00007349 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
7350 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007351
7352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007353 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007354 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007355 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00007356 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007357}
7358
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007359TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007361 sp<FakeWindowHandle> window =
7362 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7363 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007364
Vishnu Nair47074b82020-08-14 11:54:47 -07007365 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007366 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007367 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007368
7369 window->consumeFocusEvent(true);
7370
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007371 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007372
7373 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007374 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007375
7376 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007377 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00007378 mFakePolicy->assertUserActivityPoked();
7379}
7380
7381TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
7382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007383 sp<FakeWindowHandle> window =
7384 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7385 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007386
7387 window->setDisableUserActivity(true);
7388 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007389 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007390 setFocusedWindow(window);
7391
7392 window->consumeFocusEvent(true);
7393
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007394 mDispatcher->notifyKey(
7395 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007396
7397 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007398 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007399
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007400 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007401 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00007402 mFakePolicy->assertUserActivityNotPoked();
7403}
7404
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007405TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00007406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007407 sp<FakeWindowHandle> window =
7408 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7409 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007410
7411 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007413 setFocusedWindow(window);
7414
7415 window->consumeFocusEvent(true);
7416
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007417 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7418
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007419 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007420 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007421 mDispatcher->waitForIdle();
7422
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007423 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00007424 window->assertNoEvents();
7425
7426 // Should have poked user activity
7427 mFakePolicy->assertUserActivityPoked();
7428}
7429
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007430TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00007431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007432 sp<FakeWindowHandle> window =
7433 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7434 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007435
7436 window->setDisableUserActivity(true);
7437 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007438 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007439 setFocusedWindow(window);
7440
7441 window->consumeFocusEvent(true);
7442
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007443 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7444
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007445 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007446 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007447 mDispatcher->waitForIdle();
7448
7449 // System key is not passed down
7450 window->assertNoEvents();
7451
7452 // Should have poked user activity
7453 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007454}
7455
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007456class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
7457 public ::testing::WithParamInterface<bool> {};
7458
7459TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
7460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7461 sp<FakeWindowHandle> window =
7462 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7463 ui::LogicalDisplayId::DEFAULT);
7464
7465 window->setDisableUserActivity(GetParam());
7466
7467 window->setFocusable(true);
7468 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7469 setFocusedWindow(window);
7470
7471 window->consumeFocusEvent(true);
7472
7473 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7474 .keyCode(AKEYCODE_A)
7475 .policyFlags(0)
7476 .build());
7477 mDispatcher->waitForIdle();
7478
7479 // Key is not passed down
7480 window->assertNoEvents();
7481
7482 // Should not have poked user activity
7483 mFakePolicy->assertUserActivityNotPoked();
7484}
7485
7486INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
7487 ::testing::Bool());
7488
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007489TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
7490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007491 sp<FakeWindowHandle> window =
7492 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7493 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007494
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007495 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007496
7497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007498 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007499 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007500 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7501
7502 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007503 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007504
7505 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007506 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007507 mFakePolicy->assertUserActivityPoked();
7508}
7509
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007510TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007512 sp<FakeWindowHandle> window =
7513 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7514 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007515
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007516 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007517
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007518 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007519 mDispatcher->waitForIdle();
7520
7521 window->assertNoEvents();
7522}
7523
7524// If a window is touchable, but does not have focus, it should receive motion events, but not keys
7525TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07007526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007527 sp<FakeWindowHandle> window =
7528 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7529 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007530
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007532
7533 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007534 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007535 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00007536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007537 AINPUT_SOURCE_TOUCHSCREEN,
7538 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007539
7540 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007541 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007542 window->assertNoEvents(); // Key event or focus event will not be received
7543}
7544
arthurhungea3f4fc2020-12-21 23:18:53 +08007545TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
7546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7547
arthurhungea3f4fc2020-12-21 23:18:53 +08007548 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007549 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007550 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007551 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08007552
arthurhungea3f4fc2020-12-21 23:18:53 +08007553 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007554 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007555 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007556 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08007557
7558 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007559 mDispatcher->onWindowInfosChanged(
7560 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08007561
7562 PointF pointInFirst = {300, 200};
7563 PointF pointInSecond = {300, 600};
7564
7565 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007566 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007567 AINPUT_SOURCE_TOUCHSCREEN,
7568 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007569 // Only the first window should get the down event
7570 firstWindow->consumeMotionDown();
7571 secondWindow->assertNoEvents();
7572
7573 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007574 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007575 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007576 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007577 // The first window gets a move and the second a down
7578 firstWindow->consumeMotionMove();
7579 secondWindow->consumeMotionDown();
7580
7581 // Send pointer cancel to the second window
7582 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007583 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7584 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08007585 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00007586 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08007587 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007588 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7589 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08007590
7591 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007592 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007593 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08007594 // The first window gets up and the second gets nothing.
7595 firstWindow->consumeMotionUp();
7596 secondWindow->assertNoEvents();
7597}
7598
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007599TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
7600 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7601
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007602 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7603 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007604 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007605 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
7606 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
7607 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
7608
Harry Cutts33476232023-01-30 19:57:29 +00007609 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007610 window->assertNoEvents();
7611 mDispatcher->waitForIdle();
7612}
7613
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007614using InputDispatcherMonitorTest = InputDispatcherTest;
7615
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007616/**
7617 * Two entities that receive touch: A window, and a global monitor.
7618 * The touch goes to the window, and then the window disappears.
7619 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7620 * for the monitor, as well.
7621 * 1. foregroundWindow
7622 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7623 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007624TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007626 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7627 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007628
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007629 FakeMonitorReceiver monitor =
7630 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007631
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007632 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007634 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7635 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7637
7638 // Both the foreground window and the global monitor should receive the touch down
7639 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007640 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007641
7642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007643 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007644 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7646
7647 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007648 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007649
7650 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007651 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007652 window->consumeMotionCancel();
7653 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7654
7655 // If more events come in, there will be no more foreground window to send them to. This will
7656 // cause a cancel for the monitor, as well.
7657 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007659 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007660 << "Injection should fail because the window was removed";
7661 window->assertNoEvents();
7662 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007663 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007664}
7665
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007666TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07007667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007668 sp<FakeWindowHandle> window =
7669 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7670 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007672
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007673 FakeMonitorReceiver monitor =
7674 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007675
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007677 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7678 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007680 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7681 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007682}
7683
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007684TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007685 FakeMonitorReceiver monitor =
7686 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007687
Chris Yea209fde2020-07-22 13:54:51 -07007688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007689 sp<FakeWindowHandle> window =
7690 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7691 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007693
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007695 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7696 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007698 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7699 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007700
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007701 // Pilfer pointers from the monitor.
7702 // This should not do anything and the window should continue to receive events.
7703 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007704
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007706 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007707 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007709
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007710 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7711 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007712}
7713
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007714TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007716 sp<FakeWindowHandle> window =
7717 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7718 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007719 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007720 window->setWindowOffset(20, 40);
7721 window->setWindowTransform(0, 1, -1, 0);
7722
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007723 FakeMonitorReceiver monitor =
7724 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007725
7726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7728 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007730 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007731 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7732 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007733 // Even though window has transform, gesture monitor must not.
7734 ASSERT_EQ(ui::Transform(), event->getTransform());
7735}
7736
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007737TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007739 FakeMonitorReceiver monitor =
7740 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007741
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007742 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007743 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7744 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007745 << "Injection should fail if there is a monitor, but no touchable window";
7746 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007747}
7748
Linnan Lid8150952024-01-26 18:07:17 +00007749/**
7750 * Two displays
7751 * The first monitor has a foreground window, a monitor
7752 * The second window has only one monitor.
7753 * We first inject a Down event into the first display, this injection should succeed and both
7754 * the foreground window and monitor should receive a down event, then inject a Down event into
7755 * the second display as well, this injection should fail, at this point, the first display
7756 * window and monitor should not receive a cancel or any other event.
7757 * Continue to inject Move and UP events to the first display, the events should be received
7758 * normally by the foreground window and monitor.
7759 */
7760TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007762 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7763 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007764
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007765 FakeMonitorReceiver monitor =
7766 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007767 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7768
7769 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007771 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7772 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007773 << "The down event injected into the first display should succeed";
7774
7775 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007776 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007777
7778 ASSERT_EQ(InputEventInjectionResult::FAILED,
7779 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7780 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007781 << "The down event injected into the second display should fail since there's no "
7782 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007783
7784 // Continue to inject event to first display.
7785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7786 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007787 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007788 << "The move event injected into the first display should succeed";
7789
7790 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007791 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007792
7793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007794 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007795 {110, 220}))
7796 << "The up event injected into the first display should succeed";
7797
7798 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007799 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007800
7801 window->assertNoEvents();
7802 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007803 secondMonitor.assertNoEvents();
7804}
7805
7806/**
7807 * Two displays
7808 * There is a monitor and foreground window on each display.
7809 * First, we inject down events into each of the two displays, at this point, the foreground windows
7810 * and monitors on both displays should receive down events.
7811 * At this point, the foreground window of the second display goes away, the gone window should
7812 * receive the cancel event, and the other windows and monitors should not receive any events.
7813 * Inject a move event into the second display. At this point, the injection should fail because
7814 * the second display no longer has a foreground window. At this point, the monitor on the second
7815 * display should receive a cancel event, and any windows or monitors on the first display should
7816 * not receive any events, and any subsequent injection of events into the second display should
7817 * also fail.
7818 * Continue to inject events into the first display, and the events should all be injected
7819 * successfully and received normally.
7820 */
7821TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007823 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7824 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007825 sp<FakeWindowHandle> secondWindow =
7826 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7827 SECOND_DISPLAY_ID);
7828
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007829 FakeMonitorReceiver monitor =
7830 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007831 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7832
7833 // There is a foreground window on both displays.
7834 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7837 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007838 << "The down event injected into the first display should succeed";
7839
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007840 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7841 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007842
7843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7844 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7845 {100, 200}))
7846 << "The down event injected into the second display should succeed";
7847
Linnan Lid8150952024-01-26 18:07:17 +00007848 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7849 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7850
7851 // Now second window is gone away.
7852 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7853
7854 // The gone window should receive a cancel, and the monitor on the second display should not
7855 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007856 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7857 secondMonitor.assertNoEvents();
7858
7859 ASSERT_EQ(InputEventInjectionResult::FAILED,
7860 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7861 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007862 << "The move event injected into the second display should fail because there's no "
7863 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007864 // Now the monitor on the second display should receive a cancel event.
7865 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007866
7867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7868 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007869 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007870 << "The move event injected into the first display should succeed";
7871
7872 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007873 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007874
7875 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007876 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7877 {110, 220}))
7878 << "The up event injected into the second display should fail because there's no "
7879 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007880
7881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007882 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007883 {110, 220}))
7884 << "The up event injected into the first display should succeed";
7885
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007886 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7887 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007888
Linnan Lid8150952024-01-26 18:07:17 +00007889 window->assertNoEvents();
7890 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007891 secondWindow->assertNoEvents();
7892 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007893}
7894
7895/**
7896 * One display with transform
7897 * There is a foreground window and a monitor on the display
7898 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7899 * event and move event, then let the foreground window go away, the foreground window receives
7900 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7901 * by the monitor should be with the same transform as the display
7902 */
7903TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7904 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007905 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7906 ui::LogicalDisplayId::DEFAULT);
7907 FakeMonitorReceiver monitor =
7908 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007909
7910 ui::Transform transform;
7911 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7912
7913 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007914 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007915 displayInfo.transform = transform;
7916
7917 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7918
7919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007920 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7921 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007922 << "The down event injected should succeed";
7923
7924 window->consumeMotionDown();
7925 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7926 EXPECT_EQ(transform, downMotionEvent->getTransform());
7927 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7928
7929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7930 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007931 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007932 << "The move event injected should succeed";
7933
7934 window->consumeMotionMove();
7935 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7936 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7937 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7938
7939 // Let foreground window gone
7940 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7941
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007942 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007943 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007944
7945 ASSERT_EQ(InputEventInjectionResult::FAILED,
7946 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007947 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007948 << "The move event injected should failed";
7949 // Now foreground should not receive any events, but monitor should receive a cancel event
7950 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007951 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7952 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007953 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007954 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7955
7956 // Other event inject to this display should fail.
7957 ASSERT_EQ(InputEventInjectionResult::FAILED,
7958 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007959 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007960 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007961 window->assertNoEvents();
7962 monitor.assertNoEvents();
7963}
7964
chaviw81e2bb92019-12-18 15:03:51 -08007965TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007966 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007967 sp<FakeWindowHandle> window =
7968 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7969 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007970
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007971 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007972
7973 NotifyMotionArgs motionArgs =
7974 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007975 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007976
Prabir Pradhan678438e2023-04-13 19:32:51 +00007977 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007978 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007979 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007980
7981 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007982 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007983 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7984 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7985 motionArgs.pointerCoords[0].getX() - 10);
7986
Prabir Pradhan678438e2023-04-13 19:32:51 +00007987 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007988 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007989}
7990
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007991/**
7992 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7993 * the device default right away. In the test scenario, we check both the default value,
7994 * and the action of enabling / disabling.
7995 */
7996TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007998 sp<FakeWindowHandle> window =
7999 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8000 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08008001 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008002
8003 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008004 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008005 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008006
8007 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008008 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008009 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008010 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008011
8012 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07008013 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008014 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00008015 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008016
8017 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08008018 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008019 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008020 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07008021 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008022 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008023 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008024 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008025
8026 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07008027 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008028 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00008029 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008030
8031 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08008032 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008033 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008034 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07008035 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008036 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008037 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008038 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008039
8040 window->assertNoEvents();
8041}
8042
Gang Wange9087892020-01-07 12:17:14 -05008043TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07008044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008045 sp<FakeWindowHandle> window =
8046 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8047 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05008048
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008049 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008050 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05008051
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008052 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008053 setFocusedWindow(window);
8054
Harry Cutts33476232023-01-30 19:57:29 +00008055 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05008056
Prabir Pradhan678438e2023-04-13 19:32:51 +00008057 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
8058 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05008059
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008060 std::unique_ptr<KeyEvent> event = window->consumeKey();
8061 ASSERT_NE(event, nullptr);
8062 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05008063 ASSERT_NE(verified, nullptr);
8064 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
8065
8066 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
8067 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
8068 ASSERT_EQ(keyArgs.source, verified->source);
8069 ASSERT_EQ(keyArgs.displayId, verified->displayId);
8070
8071 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
8072
8073 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05008074 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08008075 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05008076 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
8077 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
8078 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
8079 ASSERT_EQ(0, verifiedKey.repeatCount);
8080}
8081
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008082TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07008083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008084 sp<FakeWindowHandle> window =
8085 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8086 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008087
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008088 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008089
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008090 ui::Transform transform;
8091 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8092
8093 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008094 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008095 displayInfo.transform = transform;
8096
Patrick Williamsd828f302023-04-28 17:52:08 -05008097 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008098
Prabir Pradhan678438e2023-04-13 19:32:51 +00008099 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008100 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008101 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008102 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008103
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008104 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
8105 ASSERT_NE(nullptr, event);
8106 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008107 ASSERT_NE(verified, nullptr);
8108 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
8109
8110 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
8111 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
8112 EXPECT_EQ(motionArgs.source, verified->source);
8113 EXPECT_EQ(motionArgs.displayId, verified->displayId);
8114
8115 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
8116
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008117 const vec2 rawXY =
8118 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
8119 motionArgs.pointerCoords[0].getXYValue());
8120 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
8121 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008122 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008123 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08008124 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008125 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
8126 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
8127}
8128
chaviw09c8d2d2020-08-24 15:48:26 -07008129/**
8130 * Ensure that separate calls to sign the same data are generating the same key.
8131 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
8132 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
8133 * tests.
8134 */
8135TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
8136 KeyEvent event = getTestKeyEvent();
8137 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8138
8139 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
8140 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
8141 ASSERT_EQ(hmac1, hmac2);
8142}
8143
8144/**
8145 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
8146 */
8147TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
8148 KeyEvent event = getTestKeyEvent();
8149 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8150 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
8151
8152 verifiedEvent.deviceId += 1;
8153 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8154
8155 verifiedEvent.source += 1;
8156 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8157
8158 verifiedEvent.eventTimeNanos += 1;
8159 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8160
Linnan Li13bf76a2024-05-05 19:18:02 +08008161 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07008162 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8163
8164 verifiedEvent.action += 1;
8165 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8166
8167 verifiedEvent.downTimeNanos += 1;
8168 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8169
8170 verifiedEvent.flags += 1;
8171 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8172
8173 verifiedEvent.keyCode += 1;
8174 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8175
8176 verifiedEvent.scanCode += 1;
8177 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8178
8179 verifiedEvent.metaState += 1;
8180 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8181
8182 verifiedEvent.repeatCount += 1;
8183 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8184}
8185
Vishnu Nair958da932020-08-21 17:12:37 -07008186TEST_F(InputDispatcherTest, SetFocusedWindow) {
8187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008188 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8189 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008190 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008191 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8192 ui::LogicalDisplayId::DEFAULT);
8193 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008194
8195 // Top window is also focusable but is not granted focus.
8196 windowTop->setFocusable(true);
8197 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008198 mDispatcher->onWindowInfosChanged(
8199 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008200 setFocusedWindow(windowSecond);
8201
8202 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008204 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008205
8206 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008207 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008208 windowTop->assertNoEvents();
8209}
8210
8211TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
8212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008213 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8214 ui::LogicalDisplayId::DEFAULT);
8215 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008216
8217 window->setFocusable(true);
8218 // Release channel for window is no longer valid.
8219 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008220 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008221 setFocusedWindow(window);
8222
8223 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008224 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07008225
8226 // window channel is invalid, so it should not receive any input event.
8227 window->assertNoEvents();
8228}
8229
8230TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
8231 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008232 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8233 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008234 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008235 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008236
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008237 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008238 setFocusedWindow(window);
8239
8240 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008241 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07008242
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008243 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07008244 window->assertNoEvents();
8245}
8246
8247TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
8248 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008249 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8250 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008251 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008252 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8253 ui::LogicalDisplayId::DEFAULT);
8254 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008255
8256 windowTop->setFocusable(true);
8257 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008258 mDispatcher->onWindowInfosChanged(
8259 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008260 setFocusedWindow(windowTop);
8261 windowTop->consumeFocusEvent(true);
8262
Chavi Weingarten847e8512023-03-29 00:26:09 +00008263 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008264 mDispatcher->onWindowInfosChanged(
8265 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008266 windowSecond->consumeFocusEvent(true);
8267 windowTop->consumeFocusEvent(false);
8268
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008270 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008271
8272 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008273 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008274}
8275
Chavi Weingarten847e8512023-03-29 00:26:09 +00008276TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07008277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008278 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8279 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008280 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008281 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8282 ui::LogicalDisplayId::DEFAULT);
8283 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008284
8285 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00008286 windowSecond->setFocusable(false);
8287 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008288 mDispatcher->onWindowInfosChanged(
8289 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00008290 setFocusedWindow(windowTop);
8291 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07008292
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00008294 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008295
8296 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008297 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008298 windowSecond->assertNoEvents();
8299}
8300
8301TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
8302 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008303 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8304 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008305 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008306 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008307 ui::LogicalDisplayId::DEFAULT);
8308 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008309
8310 window->setFocusable(true);
8311 previousFocusedWindow->setFocusable(true);
8312 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008313 mDispatcher->onWindowInfosChanged(
8314 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008315 setFocusedWindow(previousFocusedWindow);
8316 previousFocusedWindow->consumeFocusEvent(true);
8317
8318 // Requesting focus on invisible window takes focus from currently focused window.
8319 setFocusedWindow(window);
8320 previousFocusedWindow->consumeFocusEvent(false);
8321
8322 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008324 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008325 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008326
8327 // Window does not get focus event or key down.
8328 window->assertNoEvents();
8329
8330 // Window becomes visible.
8331 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008332 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008333
8334 // Window receives focus event.
8335 window->consumeFocusEvent(true);
8336 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008337 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008338}
8339
Vishnu Nair599f1412021-06-21 10:39:58 -07008340TEST_F(InputDispatcherTest, DisplayRemoved) {
8341 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008342 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
8343 ui::LogicalDisplayId::DEFAULT);
8344 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07008345
8346 // window is granted focus.
8347 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07008349 setFocusedWindow(window);
8350 window->consumeFocusEvent(true);
8351
8352 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008353 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07008354 window->consumeFocusEvent(false);
8355}
8356
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008357/**
8358 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
8359 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
8360 * of the 'slipperyEnterWindow'.
8361 *
8362 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
8363 * a way so that the touched location is no longer covered by the top window.
8364 *
8365 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
8366 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
8367 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
8368 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
8369 * with ACTION_DOWN).
8370 * Thus, the touch has been transferred from the top window into the bottom window, because the top
8371 * window moved itself away from the touched location and had Flag::SLIPPERY.
8372 *
8373 * Even though the top window moved away from the touched location, it is still obscuring the bottom
8374 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
8375 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
8376 *
8377 * In this test, we ensure that the event received by the bottom window has
8378 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
8379 */
8380TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008381 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008382 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008383
8384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008385 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008386
8387 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008388 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8389 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008390 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008391 // Make sure this one overlaps the bottom window
8392 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
8393 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
8394 // one. Windows with the same owner are not considered to be occluding each other.
8395 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
8396
8397 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008398 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8399 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008400 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
8401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008402 mDispatcher->onWindowInfosChanged(
8403 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008404
8405 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00008406 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008407 AINPUT_SOURCE_TOUCHSCREEN,
8408 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008409 slipperyExitWindow->consumeMotionDown();
8410 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008411 mDispatcher->onWindowInfosChanged(
8412 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008413
Prabir Pradhan678438e2023-04-13 19:32:51 +00008414 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008415 AINPUT_SOURCE_TOUCHSCREEN,
8416 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008417
8418 slipperyExitWindow->consumeMotionCancel();
8419
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008420 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008421 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8422}
8423
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008424/**
8425 * Two windows, one on the left and another on the right. The left window is slippery. The right
8426 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
8427 * touch moves from the left window into the right window, the gesture should continue to go to the
8428 * left window. Touch shouldn't slip because the right window can't receive touches. This test
8429 * reproduces a crash.
8430 */
8431TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
8432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8433
8434 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008435 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8436 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008437 leftSlipperyWindow->setSlippery(true);
8438 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
8439
8440 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008441 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8442 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008443 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
8444 rightDropTouchesWindow->setDropInput(true);
8445
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008446 mDispatcher->onWindowInfosChanged(
8447 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008448
8449 // Start touch in the left window
8450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8451 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8452 .build());
8453 leftSlipperyWindow->consumeMotionDown();
8454
8455 // And move it into the right window
8456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8457 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8458 .build());
8459
8460 // Since the right window isn't eligible to receive input, touch does not slip.
8461 // The left window continues to receive the gesture.
8462 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8463 rightDropTouchesWindow->assertNoEvents();
8464}
8465
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008466/**
8467 * A single window is on screen first. Touch is injected into that window. Next, a second window
8468 * appears. Since the first window is slippery, touch will move from the first window to the second.
8469 */
8470TEST_F(InputDispatcherTest, InjectedTouchSlips) {
8471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8472 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008473 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
8474 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008475 originalWindow->setFrame(Rect(0, 0, 200, 200));
8476 originalWindow->setSlippery(true);
8477
8478 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008479 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
8480 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008481 appearingWindow->setFrame(Rect(0, 0, 200, 200));
8482
8483 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
8484
8485 // Touch down on the original window
8486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8487 injectMotionEvent(*mDispatcher,
8488 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8489 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
8490 .build()));
8491 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8492
8493 // Now, a new window appears. This could be, for example, a notification shade that appears
8494 // after user starts to drag down on the launcher window.
8495 mDispatcher->onWindowInfosChanged(
8496 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
8497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8498 injectMotionEvent(*mDispatcher,
8499 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8500 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
8501 .build()));
8502 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8503 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8505 injectMotionEvent(*mDispatcher,
8506 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8507 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
8508 .build()));
8509 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8510
8511 originalWindow->assertNoEvents();
8512 appearingWindow->assertNoEvents();
8513}
8514
Linnan Li49b2b202024-04-12 12:46:40 +08008515/**
8516 * Three windows:
8517 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
8518 * - right window
8519 * - spy window
8520 * The three windows do not overlap.
8521 *
8522 * We have two devices reporting events:
8523 * - Device A reports ACTION_DOWN, which lands in the left window
8524 * - Device B reports ACTION_DOWN, which lands in the spy window.
8525 * - Now, device B reports ACTION_MOVE events which move to the right window.
8526 *
8527 * The right window should not receive any events because the spy window is not a foreground window,
8528 * and also it does not support slippery touches.
8529 */
8530TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
8531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8532 sp<FakeWindowHandle> leftWindow =
8533 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008534 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008535 leftWindow->setFrame(Rect(0, 0, 100, 100));
8536 leftWindow->setSlippery(true);
8537
8538 sp<FakeWindowHandle> rightWindow =
8539 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008540 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008541 rightWindow->setFrame(Rect(100, 0, 200, 100));
8542
8543 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008544 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8545 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008546 spyWindow->setFrame(Rect(200, 0, 300, 100));
8547 spyWindow->setSpy(true);
8548 spyWindow->setTrustedOverlay(true);
8549
8550 mDispatcher->onWindowInfosChanged(
8551 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
8552
8553 const DeviceId deviceA = 9;
8554 const DeviceId deviceB = 3;
8555
8556 // Tap on left window with device A
8557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8558 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8559 .deviceId(deviceA)
8560 .build());
8561 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8562
8563 // Tap on spy window with device B
8564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8565 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8566 .deviceId(deviceB)
8567 .build());
8568 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8569
8570 // Move to right window with device B. Touches should not slip to the right window, because spy
8571 // window is not a foreground window, and it does not have FLAG_SLIPPERY
8572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8573 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8574 .deviceId(deviceB)
8575 .build());
8576 leftWindow->assertNoEvents();
8577 rightWindow->assertNoEvents();
8578 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8579}
8580
8581/**
8582 * Three windows arranged horizontally and without any overlap.
8583 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
8584 *
8585 * We have two devices reporting events:
8586 * - Device A reports ACTION_DOWN which lands in the left window
8587 * - Device B reports ACTION_DOWN which lands in the right window
8588 * - Device B reports ACTION_MOVE that shifts to the middle window.
8589 * This should cause touches for Device B to slip from the right window to the middle window.
8590 * The right window should receive ACTION_CANCEL for device B and the
8591 * middle window should receive down event for Device B.
8592 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
8593 */
8594TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07008595 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08008596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8597 sp<FakeWindowHandle> leftWindow =
8598 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008599 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008600 leftWindow->setFrame(Rect(0, 0, 100, 100));
8601 leftWindow->setSlippery(true);
8602
8603 sp<FakeWindowHandle> middleWindow =
8604 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008605 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008606 middleWindow->setFrame(Rect(100, 0, 200, 100));
8607
8608 sp<FakeWindowHandle> rightWindow =
8609 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008610 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008611 rightWindow->setFrame(Rect(200, 0, 300, 100));
8612 rightWindow->setSlippery(true);
8613
8614 mDispatcher->onWindowInfosChanged(
8615 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
8616 {},
8617 0,
8618 0});
8619
8620 const DeviceId deviceA = 9;
8621 const DeviceId deviceB = 3;
8622
8623 // Tap on left window with device A
8624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8625 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8626 .deviceId(deviceA)
8627 .build());
8628 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8629
8630 // Tap on right window with device B
8631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8632 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8633 .deviceId(deviceB)
8634 .build());
8635 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8636
8637 // Move to middle window with device B. Touches should slip to middle window, because right
8638 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8640 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8641 .deviceId(deviceB)
8642 .build());
8643 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8644 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8645
8646 // Move to middle window with device A. Touches should slip to middle window, because left
8647 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8649 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8650 .deviceId(deviceA)
8651 .build());
8652 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8653 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8654
8655 // Ensure that middle window can receive the remaining move events.
8656 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8657 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8658 .deviceId(deviceB)
8659 .build());
8660 leftWindow->assertNoEvents();
8661 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8662 rightWindow->assertNoEvents();
8663}
8664
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008665TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008666 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8668
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008669 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8670 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008671 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008672 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008673
8674 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008675 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8676 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008677 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008678 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008679 rightSpy->setSpy(true);
8680 rightSpy->setTrustedOverlay(true);
8681
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008682 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8683 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008684 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008685 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008687 mDispatcher->onWindowInfosChanged(
8688 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008689
8690 // Touch in the left window
8691 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8692 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8693 .build());
8694 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8695 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008696 ASSERT_NO_FATAL_FAILURE(
8697 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008698
8699 // Touch another finger over the right windows
8700 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8701 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8702 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8703 .build());
8704 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8705 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8706 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8707 mDispatcher->waitForIdle();
8708 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008709 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8710 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008711
8712 // Release finger over left window. The UP actions are not treated as device interaction.
8713 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8714 // is part of the UP action, we do not treat this as device interaction.
8715 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8716 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8717 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8718 .build());
8719 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8720 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8721 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8722 mDispatcher->waitForIdle();
8723 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8724
8725 // Move remaining finger
8726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8727 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8728 .build());
8729 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8730 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8731 mDispatcher->waitForIdle();
8732 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008733 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008734
8735 // Release all fingers
8736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8737 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8738 .build());
8739 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8740 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8741 mDispatcher->waitForIdle();
8742 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8743}
8744
8745TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8747
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8749 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008750 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008751 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008752
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008754 setFocusedWindow(window);
8755 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8756
8757 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008758 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008759 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008760 ASSERT_NO_FATAL_FAILURE(
8761 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008762
8763 // The UP actions are not treated as device interaction.
8764 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008765 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008766 mDispatcher->waitForIdle();
8767 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8768}
8769
Prabir Pradhan5893d362023-11-17 04:30:40 +00008770TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8772
8773 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008774 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008775 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008776 sp<FakeWindowHandle> right =
8777 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8778 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008779 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008780 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8781 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008782 spy->setFrame(Rect(0, 0, 200, 100));
8783 spy->setTrustedOverlay(true);
8784 spy->setSpy(true);
8785
8786 mDispatcher->onWindowInfosChanged(
8787 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8788
8789 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008790 NotifyMotionArgs notifyArgs =
8791 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8792 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008793 mDispatcher->notifyMotion(notifyArgs);
8794
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008795 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008796 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8797 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008798 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008799 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8800 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008801 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008802 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8803
8804 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008805 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8806 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008807 mDispatcher->notifyMotion(notifyArgs);
8808
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008809 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008810 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8811 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008812 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008813 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8814 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008815 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008816 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8817
8818 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8819}
8820
Linnan Liccf6ce32024-04-11 20:32:13 +08008821/**
8822 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8823 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8824 * the previous window should receive this event and not be dropped.
8825 */
8826TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07008827 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Linnan Liccf6ce32024-04-11 20:32:13 +08008828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008829 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8830 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008831 window->setFrame(Rect(0, 0, 100, 100));
8832 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8833
8834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8835 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8836 .build());
8837
8838 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8839
8840 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8841 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8842 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8843 .build());
8844
8845 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8846}
8847
8848/**
8849 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8850 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8851 * previous window should receive deviceB's event and it should be dropped.
8852 */
8853TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008855 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8856 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008857 window->setFrame(Rect(0, 0, 100, 100));
8858 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8859
8860 const DeviceId deviceA = 9;
8861 const DeviceId deviceB = 3;
8862
8863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8864 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8865 .deviceId(deviceA)
8866 .build());
8867 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8868
8869 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8870 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8871 .deviceId(deviceB)
8872 .build());
8873 window->assertNoEvents();
8874}
8875
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008876class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8877protected:
8878 std::shared_ptr<FakeApplicationHandle> mApp;
8879 sp<FakeWindowHandle> mWindow;
8880
8881 virtual void SetUp() override {
8882 InputDispatcherTest::SetUp();
8883
8884 mApp = std::make_shared<FakeApplicationHandle>();
8885
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008886 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8887 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008888 mWindow->setFrame(Rect(0, 0, 100, 100));
8889
8890 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8891 setFocusedWindow(mWindow);
8892 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8893 }
8894
8895 void setFallback(int32_t keycode) {
8896 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8897 return KeyEventBuilder(event).keyCode(keycode).build();
8898 });
8899 }
8900
8901 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008902 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8903 ASSERT_NE(nullptr, event);
8904 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008905 }
8906};
8907
8908TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8909 mDispatcher->notifyKey(
8910 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8911 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8912 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8913}
8914
8915TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8916 mDispatcher->notifyKey(
8917 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8918 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8919 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8920}
8921
8922TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8923 mDispatcher->notifyKey(
8924 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8925
8926 // Do not handle this key event.
8927 consumeKey(/*handled=*/false,
8928 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8929 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8930
8931 // Since the policy did not request any fallback to be generated, ensure there are no events.
8932 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8933}
8934
8935TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8936 setFallback(AKEYCODE_B);
8937 mDispatcher->notifyKey(
8938 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8939
8940 // Do not handle this key event.
8941 consumeKey(/*handled=*/false,
8942 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8943
8944 // Since the key was not handled, ensure the fallback event was dispatched instead.
8945 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8946 consumeKey(/*handled=*/true,
8947 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8948 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8949
8950 // Release the original key, and ensure the fallback key is also released.
8951 mDispatcher->notifyKey(
8952 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8953 consumeKey(/*handled=*/false,
8954 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8955 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8956 consumeKey(/*handled=*/true,
8957 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8958 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8959
8960 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8961 mWindow->assertNoEvents();
8962}
8963
8964TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8965 setFallback(AKEYCODE_B);
8966 mDispatcher->notifyKey(
8967 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8968
8969 // Do not handle this key event, but handle the fallback.
8970 consumeKey(/*handled=*/false,
8971 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8972 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8973 consumeKey(/*handled=*/true,
8974 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8975 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8976
8977 // Release the original key, and ensure the fallback key is also released.
8978 mDispatcher->notifyKey(
8979 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8980 // But this time, the app handles the original key.
8981 consumeKey(/*handled=*/true,
8982 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8983 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8984 // Ensure the fallback key is canceled.
8985 consumeKey(/*handled=*/true,
8986 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8987 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8988
8989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8990 mWindow->assertNoEvents();
8991}
8992
8993TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8994 setFallback(AKEYCODE_B);
8995 mDispatcher->notifyKey(
8996 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8997
8998 // Do not handle this key event.
8999 consumeKey(/*handled=*/false,
9000 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9001 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9002 // App does not handle the fallback either, so ensure another fallback is not generated.
9003 setFallback(AKEYCODE_C);
9004 consumeKey(/*handled=*/false,
9005 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9006 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9007
9008 // Release the original key, and ensure the fallback key is also released.
9009 setFallback(AKEYCODE_B);
9010 mDispatcher->notifyKey(
9011 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9012 consumeKey(/*handled=*/false,
9013 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9014 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9015 consumeKey(/*handled=*/false,
9016 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9017 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9018
9019 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9020 mWindow->assertNoEvents();
9021}
9022
9023TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
9024 setFallback(AKEYCODE_B);
9025 mDispatcher->notifyKey(
9026 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9027
9028 // Do not handle this key event, so fallback is generated.
9029 consumeKey(/*handled=*/false,
9030 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9031 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9032 consumeKey(/*handled=*/true,
9033 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9034 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9035
9036 // Release the original key, but assume the policy is misbehaving and it
9037 // generates an inconsistent fallback to the one from the DOWN event.
9038 setFallback(AKEYCODE_C);
9039 mDispatcher->notifyKey(
9040 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9041 consumeKey(/*handled=*/false,
9042 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9043 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9044 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
9045 consumeKey(/*handled=*/true,
9046 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9047 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9048
9049 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9050 mWindow->assertNoEvents();
9051}
9052
9053TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
9054 setFallback(AKEYCODE_B);
9055 mDispatcher->notifyKey(
9056 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9057
9058 // Do not handle this key event, so fallback is generated.
9059 consumeKey(/*handled=*/false,
9060 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9061 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9062 consumeKey(/*handled=*/true,
9063 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9064 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9065
9066 // The original key is canceled.
9067 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
9068 .keyCode(AKEYCODE_A)
9069 .addFlag(AKEY_EVENT_FLAG_CANCELED)
9070 .build());
9071 consumeKey(/*handled=*/false,
9072 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9073 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9074 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9075 // Ensure the fallback key is also canceled due to the original key being canceled.
9076 consumeKey(/*handled=*/true,
9077 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9078 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9079
9080 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9081 mWindow->assertNoEvents();
9082}
9083
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00009084TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00009085 setFallback(AKEYCODE_B);
9086 mDispatcher->notifyKey(
9087 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9088
9089 // Do not handle this key event.
9090 consumeKey(/*handled=*/false,
9091 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9092 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9093 consumeKey(/*handled=*/true,
9094 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9095 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9096
9097 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9098 // When the unhandled key is reported to the policy next, remove the input channel.
9099 mDispatcher->removeInputChannel(mWindow->getToken());
9100 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9101 });
9102 // Release the original key, and let the app now handle the previously unhandled key.
9103 // This should result in the previously generated fallback key to be cancelled.
9104 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
9105 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
9106 // without holding the lock, because it need to synchronously fetch the fallback key. While in
9107 // the policy call, we will now remove the input channel. Once the policy call returns, the
9108 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
9109 // not cause any crashes.
9110 mDispatcher->notifyKey(
9111 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9112 consumeKey(/*handled=*/true,
9113 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9114 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9115}
9116
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00009117TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
9118 setFallback(AKEYCODE_B);
9119 mDispatcher->notifyKey(
9120 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9121
9122 // Do not handle this key event.
9123 consumeKey(/*handled=*/false,
9124 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9125 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9126 consumeKey(/*handled=*/true,
9127 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9128 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9129
9130 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9131 // When the unhandled key is reported to the policy next, remove the window.
9132 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9133 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9134 });
9135 // Release the original key, which the app will not handle. When this unhandled key is reported
9136 // to the policy, the window will be removed.
9137 mDispatcher->notifyKey(
9138 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9139 consumeKey(/*handled=*/false,
9140 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9141 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9142
9143 // Since the window was removed, it loses focus, and the channel state will be reset.
9144 consumeKey(/*handled=*/true,
9145 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9146 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9147 mWindow->consumeFocusEvent(false);
9148 mWindow->assertNoEvents();
9149}
9150
9151TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
9152 setFallback(AKEYCODE_B);
9153 mDispatcher->notifyKey(
9154 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9155
9156 // Do not handle this key event.
9157 consumeKey(/*handled=*/false,
9158 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9159 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9160 const auto [seq, event] = mWindow->receiveEvent();
9161 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
9162 ASSERT_EQ(event->getType(), InputEventType::KEY);
9163 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
9164 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9165 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9166
9167 // Remove the window now, which should generate a cancellations and make the window lose focus.
9168 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9169 consumeKey(/*handled=*/true,
9170 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9171 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9172 consumeKey(/*handled=*/true,
9173 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9174 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9175 mWindow->consumeFocusEvent(false);
9176
9177 // Finish the event by reporting it as handled.
9178 mWindow->finishEvent(*seq);
9179 mWindow->assertNoEvents();
9180}
9181
Garfield Tan1c7bc862020-01-28 13:24:04 -08009182class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
9183protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08009184 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
9185 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009186 static constexpr bool KEY_REPEAT_ENABLED = true;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009187
Chris Yea209fde2020-07-22 13:54:51 -07009188 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009189 sp<FakeWindowHandle> mWindow;
9190
9191 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00009192 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08009193
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009194 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9195 KEY_REPEAT_ENABLED);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009196 setUpWindow();
9197 }
9198
9199 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07009200 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009201 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
9202 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009203
Vishnu Nair47074b82020-08-14 11:54:47 -07009204 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009205 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009206 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009207 mWindow->consumeFocusEvent(true);
9208 }
9209
Chris Ye2ad95392020-09-01 13:44:44 -07009210 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009211 NotifyKeyArgs keyArgs =
9212 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07009213 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009214 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00009215 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009216
9217 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009218 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009219 }
9220
9221 void expectKeyRepeatOnce(int32_t repeatCount) {
9222 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009223 mWindow->consumeKeyEvent(
9224 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08009225 }
9226
Chris Ye2ad95392020-09-01 13:44:44 -07009227 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009228 NotifyKeyArgs keyArgs =
9229 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07009230 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009231 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00009232 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009233
9234 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009235 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00009236 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009237 }
Hu Guofe3c8f12023-09-22 17:20:15 +08009238
9239 void injectKeyRepeat(int32_t repeatCount) {
9240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009241 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
9242 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08009243 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9244 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08009245};
9246
9247TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00009248 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009249 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9250 expectKeyRepeatOnce(repeatCount);
9251 }
9252}
9253
9254TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00009255 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009256 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9257 expectKeyRepeatOnce(repeatCount);
9258 }
Harry Cutts33476232023-01-30 19:57:29 +00009259 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009260 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08009261 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9262 expectKeyRepeatOnce(repeatCount);
9263 }
9264}
9265
9266TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009267 sendAndConsumeKeyDown(/*deviceId=*/1);
9268 expectKeyRepeatOnce(/*repeatCount=*/1);
9269 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009270 mWindow->assertNoEvents();
9271}
9272
9273TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009274 sendAndConsumeKeyDown(/*deviceId=*/1);
9275 expectKeyRepeatOnce(/*repeatCount=*/1);
9276 sendAndConsumeKeyDown(/*deviceId=*/2);
9277 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009278 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00009279 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009280 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00009281 expectKeyRepeatOnce(/*repeatCount=*/2);
9282 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07009283 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00009284 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009285 mWindow->assertNoEvents();
9286}
9287
9288TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009289 sendAndConsumeKeyDown(/*deviceId=*/1);
9290 expectKeyRepeatOnce(/*repeatCount=*/1);
9291 sendAndConsumeKeyDown(/*deviceId=*/2);
9292 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009293 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00009294 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009295 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08009296 mWindow->assertNoEvents();
9297}
9298
liushenxiang42232912021-05-21 20:24:09 +08009299TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
9300 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00009301 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009302 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009303 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08009304 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
9305 mWindow->assertNoEvents();
9306}
9307
Garfield Tan1c7bc862020-01-28 13:24:04 -08009308TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00009309 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00009310 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009311 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009312 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9313 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009314 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009315 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08009316 }
9317}
9318
9319TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00009320 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00009321 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009322
9323 std::unordered_set<int32_t> idSet;
9324 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009325 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9326 ASSERT_NE(nullptr, repeatEvent);
9327 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08009328 EXPECT_EQ(idSet.end(), idSet.find(id));
9329 idSet.insert(id);
9330 }
9331}
9332
Hu Guofe3c8f12023-09-22 17:20:15 +08009333TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
9334 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009335 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08009336 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
9337 expectKeyRepeatOnce(repeatCount);
9338 }
9339 injectKeyRepeat(1);
9340 // Expect repeatCount to be 3 instead of 1
9341 expectKeyRepeatOnce(3);
9342}
9343
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009344TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_NoRepeatWhenKeyRepeatDisabled) {
9345 SCOPED_FLAG_OVERRIDE(keyboard_repeat_keys, true);
9346 static constexpr std::chrono::milliseconds KEY_NO_REPEAT_ASSERTION_TIMEOUT = 100ms;
9347
9348 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9349 /*repeatKeyEnabled=*/false);
9350 sendAndConsumeKeyDown(/*deviceId=*/1);
9351
9352 ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_TIMEOUT)
9353 << "Ensure the check for no key repeats extends beyond the repeat timeout duration.";
9354 ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_DELAY)
9355 << "Ensure the check for no key repeats extends beyond the repeat delay duration.";
9356
9357 // No events should be returned if key repeat is turned off.
9358 // Wait for KEY_NO_REPEAT_ASSERTION_TIMEOUT to return no events to ensure key repeat disabled.
9359 mWindow->assertNoEvents(KEY_NO_REPEAT_ASSERTION_TIMEOUT);
9360}
9361
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009362/* Test InputDispatcher for MultiDisplay */
9363class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
9364public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009365 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009366 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08009367
Chris Yea209fde2020-07-22 13:54:51 -07009368 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009369 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
9370 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009371
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009372 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009373 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07009374 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009375 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
9376
Vishnu Nair958da932020-08-21 17:12:37 -07009377 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009378 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08009379
Chris Yea209fde2020-07-22 13:54:51 -07009380 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009381 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009382 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009383 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009384 // Set focus display to second one.
9385 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00009386 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
9387
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009388 // Set focus window for second display.
9389 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07009390 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009391 mDispatcher->onWindowInfosChanged(
9392 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009393 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009394 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009395 }
9396
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009397 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009398 InputDispatcherTest::TearDown();
9399
Chris Yea209fde2020-07-22 13:54:51 -07009400 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009401 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07009402 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009403 windowInSecondary.clear();
9404 }
9405
9406protected:
Chris Yea209fde2020-07-22 13:54:51 -07009407 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009408 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07009409 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009410 sp<FakeWindowHandle> windowInSecondary;
9411};
9412
9413TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
9414 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009416 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9417 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009419 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08009420 windowInSecondary->assertNoEvents();
9421
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009422 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009424 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009425 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009426 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009427 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009428}
9429
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009430TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08009431 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009433 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009434 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009435 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08009436 windowInSecondary->assertNoEvents();
9437
9438 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009440 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009441 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009442 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009443
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009444 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009445 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08009446
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009447 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009448 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08009449
9450 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009451 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08009452 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009453 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08009454 windowInSecondary->assertNoEvents();
9455}
9456
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009457// Test per-display input monitors for motion event.
9458TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08009459 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009460 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009461 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009462 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009463
9464 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009466 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9467 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009469 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9470 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009471 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009472 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009473
9474 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009476 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009478 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009479 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009480 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08009481 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009482
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009483 // Lift up the touch from the second display
9484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009485 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009486 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9487 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
9488 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
9489
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009490 // Test inject a non-pointer motion event.
9491 // If specific a display, it will dispatch to the focused window of particular display,
9492 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009494 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
9495 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009497 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009498 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009499 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
9500 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009501}
9502
9503// Test per-display input monitors for key event.
9504TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009505 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08009506 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009507 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009508 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009509 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009510
9511 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009513 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009514 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009515 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009516 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9517 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009518}
9519
Vishnu Nair958da932020-08-21 17:12:37 -07009520TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
9521 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009522 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
9523 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009524 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009525 mDispatcher->onWindowInfosChanged(
9526 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
9527 *windowInSecondary->getInfo()},
9528 {},
9529 0,
9530 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009531 setFocusedWindow(secondWindowInPrimary);
9532 windowInPrimary->consumeFocusEvent(false);
9533 secondWindowInPrimary->consumeFocusEvent(true);
9534
9535 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009537 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009538 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009539 windowInPrimary->assertNoEvents();
9540 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009541 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009542}
9543
Arthur Hungdfd528e2021-12-08 13:23:04 +00009544TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
9545 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009546 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009547 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009548 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009549
9550 // Test touch down on primary display.
9551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009552 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9553 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009554 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009555 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9556 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009557
9558 // Test touch down on second display.
9559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009560 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9562 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9563 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9564
9565 // Trigger cancel touch.
9566 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009567 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9568 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009569 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
9570 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
9571
9572 // Test inject a move motion event, no window/monitor should receive the event.
9573 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009574 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009575 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009576 << "Inject motion event should return InputEventInjectionResult::FAILED";
9577 windowInPrimary->assertNoEvents();
9578 monitorInPrimary.assertNoEvents();
9579
9580 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009581 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00009582 SECOND_DISPLAY_ID, {110, 200}))
9583 << "Inject motion event should return InputEventInjectionResult::FAILED";
9584 windowInSecondary->assertNoEvents();
9585 monitorInSecondary.assertNoEvents();
9586}
9587
Hu Guocb134f12023-12-23 13:42:44 +00009588/**
9589 * Send a key to the primary display and to the secondary display.
9590 * Then cause the key on the primary display to be canceled by sending in a stale key.
9591 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
9592 * does not get canceled.
9593 */
9594TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
9595 // Send a key down on primary display
9596 mDispatcher->notifyKey(
9597 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009598 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009599 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9600 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009601 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
9602 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009603 windowInSecondary->assertNoEvents();
9604
9605 // Send a key down on second display
9606 mDispatcher->notifyKey(
9607 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9608 .displayId(SECOND_DISPLAY_ID)
9609 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9610 .build());
9611 windowInSecondary->consumeKeyEvent(
9612 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9613 windowInPrimary->assertNoEvents();
9614
9615 // Send a valid key up event on primary display that will be dropped because it is stale
9616 NotifyKeyArgs staleKeyUp =
9617 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009618 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009619 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9620 .build();
9621 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9622 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9623 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9624 mDispatcher->notifyKey(staleKeyUp);
9625
9626 // Only the key gesture corresponding to the dropped event should receive the cancel event.
9627 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
9628 // receive any events.
9629 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009630 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00009631 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9632 windowInSecondary->assertNoEvents();
9633}
9634
9635/**
9636 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
9637 */
9638TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
9639 // Send touch down on primary display.
9640 mDispatcher->notifyMotion(
9641 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9642 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009643 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009644 .build());
9645 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009646 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009647 windowInSecondary->assertNoEvents();
9648
9649 // Send touch down on second display.
9650 mDispatcher->notifyMotion(
9651 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9652 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9653 .displayId(SECOND_DISPLAY_ID)
9654 .build());
9655 windowInPrimary->assertNoEvents();
9656 windowInSecondary->consumeMotionEvent(
9657 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9658
9659 // inject a valid MotionEvent on primary display that will be stale when it arrives.
9660 NotifyMotionArgs staleMotionUp =
9661 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009662 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009663 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9664 .build();
9665 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9666 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9667 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9668 mDispatcher->notifyMotion(staleMotionUp);
9669
9670 // For stale motion events, we let the gesture to complete. This behaviour is different from key
9671 // events, where we would cancel the current keys instead.
9672 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9673 windowInSecondary->assertNoEvents();
9674}
9675
Jackal Guof9696682018-10-05 12:23:23 +08009676class InputFilterTest : public InputDispatcherTest {
9677protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08009678 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009679 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08009680 NotifyMotionArgs motionArgs;
9681
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009682 motionArgs =
9683 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009684 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009685 motionArgs =
9686 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009687 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009688 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009689 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009690 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009691 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08009692 } else {
9693 mFakePolicy->assertFilterInputEventWasNotCalled();
9694 }
9695 }
9696
9697 void testNotifyKey(bool expectToBeFiltered) {
9698 NotifyKeyArgs keyArgs;
9699
9700 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009701 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009702 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009703 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009704 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009705
9706 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009707 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009708 } else {
9709 mFakePolicy->assertFilterInputEventWasNotCalled();
9710 }
9711 }
9712};
9713
9714// Test InputFilter for MotionEvent
9715TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9716 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009717 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009718 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009719
9720 // Enable InputFilter
9721 mDispatcher->setInputFilterEnabled(true);
9722 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009723 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009724 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009725
9726 // Disable InputFilter
9727 mDispatcher->setInputFilterEnabled(false);
9728 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009729 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009730 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009731}
9732
9733// Test InputFilter for KeyEvent
9734TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9735 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009736 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009737
9738 // Enable InputFilter
9739 mDispatcher->setInputFilterEnabled(true);
9740 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009741 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009742
9743 // Disable InputFilter
9744 mDispatcher->setInputFilterEnabled(false);
9745 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009746 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009747}
9748
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009749// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9750// logical display coordinate space.
9751TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9752 ui::Transform firstDisplayTransform;
9753 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9754 ui::Transform secondDisplayTransform;
9755 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9756
9757 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009758 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009759 displayInfos[0].transform = firstDisplayTransform;
9760 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9761 displayInfos[1].transform = secondDisplayTransform;
9762
Patrick Williamsd828f302023-04-28 17:52:08 -05009763 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009764
9765 // Enable InputFilter
9766 mDispatcher->setInputFilterEnabled(true);
9767
9768 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009769 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9770 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009771 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009772}
9773
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009774class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9775protected:
9776 virtual void SetUp() override {
9777 InputDispatcherTest::SetUp();
9778
9779 /**
9780 * We don't need to enable input filter to test the injected event policy, but we enabled it
9781 * here to make the tests more realistic, since this policy only matters when inputfilter is
9782 * on.
9783 */
9784 mDispatcher->setInputFilterEnabled(true);
9785
9786 std::shared_ptr<InputApplicationHandle> application =
9787 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009788 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009789 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009790
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009791 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009792 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009793 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009794 setFocusedWindow(mWindow);
9795 mWindow->consumeFocusEvent(true);
9796 }
9797
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009798 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9799 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009800 KeyEvent event;
9801
9802 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9803 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009804 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9805 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009806 const int32_t additionalPolicyFlags =
9807 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009809 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009810 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009811 policyFlags | additionalPolicyFlags));
9812
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009813 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009814 }
9815
9816 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9817 int32_t flags) {
9818 MotionEvent event;
9819 PointerProperties pointerProperties[1];
9820 PointerCoords pointerCoords[1];
9821 pointerProperties[0].clear();
9822 pointerProperties[0].id = 0;
9823 pointerCoords[0].clear();
9824 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9825 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9826
9827 ui::Transform identityTransform;
9828 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9829 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9830 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9831 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9832 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009833 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009834 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009835 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009836
9837 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009839 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009840 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009841 policyFlags | additionalPolicyFlags));
9842
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009843 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009844 }
9845
9846private:
9847 sp<FakeWindowHandle> mWindow;
9848};
9849
9850TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009851 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9852 // filter. Without it, the event will no different from a regularly injected event, and the
9853 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009854 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9855 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009856}
9857
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009858TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009859 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009860 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009861 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9862}
9863
9864TEST_F(InputFilterInjectionPolicyTest,
9865 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9866 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009867 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009868 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009869}
9870
9871TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009872 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9873 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009874}
9875
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009876class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9877protected:
9878 virtual void SetUp() override {
9879 InputDispatcherTest::SetUp();
9880
9881 std::shared_ptr<FakeApplicationHandle> application =
9882 std::make_shared<FakeApplicationHandle>();
9883 application->setDispatchingTimeout(100ms);
9884 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009885 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009886 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009887 mWindow->setDispatchingTimeout(100ms);
9888 mWindow->setFocusable(true);
9889
9890 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009891 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009892
9893 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9894 setFocusedWindow(mWindow);
9895 mWindow->consumeFocusEvent(true);
9896 }
9897
Linnan Li13bf76a2024-05-05 19:18:02 +08009898 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009899 nsecs_t eventTime) {
9900 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9901 .displayId(displayId)
9902 .eventTime(eventTime)
9903 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9904 .build());
9905 mWindow->consumeMotionEvent(WithMotionAction(action));
9906 }
9907
9908private:
9909 sp<FakeWindowHandle> mWindow;
9910};
9911
9912TEST_F_WITH_FLAGS(
9913 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9914 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9915 rate_limit_user_activity_poke_in_dispatcher))) {
9916 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9917
9918 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009919 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009920 milliseconds_to_nanoseconds(50));
9921 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009922 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9923 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009924
9925 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009926 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009927 milliseconds_to_nanoseconds(130));
9928 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009929 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9930 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009931
9932 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009933 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9934 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009935 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009936 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9937 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009938
9939 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009940 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009941 milliseconds_to_nanoseconds(140));
9942 mFakePolicy->assertUserActivityNotPoked();
9943
9944 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009945 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9946 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009947 mFakePolicy->assertUserActivityNotPoked();
9948
9949 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9950 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009951 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009952 milliseconds_to_nanoseconds(160));
9953 mFakePolicy->assertUserActivityNotPoked();
9954
9955 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009956 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9957 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009958 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009959 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9960 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009961
9962 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009963 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009964 milliseconds_to_nanoseconds(300));
9965 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009966 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9967 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009968
9969 // Assert that there's no more user activity poke event.
9970 mFakePolicy->assertUserActivityNotPoked();
9971}
9972
9973TEST_F_WITH_FLAGS(
9974 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9975 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9976 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009977 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009978 milliseconds_to_nanoseconds(200));
9979 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009980 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9981 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009982
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009983 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009984 milliseconds_to_nanoseconds(280));
9985 mFakePolicy->assertUserActivityNotPoked();
9986
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009987 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009988 milliseconds_to_nanoseconds(340));
9989 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009990 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9991 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009992}
9993
9994TEST_F_WITH_FLAGS(
9995 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9996 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9997 rate_limit_user_activity_poke_in_dispatcher))) {
9998 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9999
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010000 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
10001 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -080010002 mFakePolicy->assertUserActivityPoked();
10003
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010004 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
10005 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -080010006 mFakePolicy->assertUserActivityPoked();
10007}
10008
chaviwfd6d3512019-03-25 13:23:49 -070010009class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -070010010 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -070010011 InputDispatcherTest::SetUp();
10012
Chris Yea209fde2020-07-22 13:54:51 -070010013 std::shared_ptr<FakeApplicationHandle> application =
10014 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010015 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
10016 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -070010017 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -070010018
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010019 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
10020 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -080010021 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -070010022
10023 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010024 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -070010025 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -070010026
10027 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010028 mDispatcher->onWindowInfosChanged(
10029 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010030 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +010010031 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -070010032 }
10033
Prabir Pradhan3608aad2019-10-02 17:08:26 -070010034 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -070010035 InputDispatcherTest::TearDown();
10036
10037 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -080010038 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -070010039 }
10040
10041protected:
10042 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -080010043 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -070010044 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -070010045};
10046
10047// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
10048// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
10049// the onPointerDownOutsideFocus callback.
10050TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010052 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10053 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010055 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010056
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010057 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -070010058 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
10059}
10060
10061// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
10062// DOWN on the window that doesn't have focus. Ensure no window received the
10063// onPointerDownOutsideFocus callback.
10064TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010066 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010067 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010069 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010070
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010071 ASSERT_TRUE(mDispatcher->waitForIdle());
10072 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010073}
10074
10075// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
10076// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
10077TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -080010078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010079 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010080 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010081 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -070010082
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010083 ASSERT_TRUE(mDispatcher->waitForIdle());
10084 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010085}
10086
10087// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
10088// DOWN on the window that already has focus. Ensure no window received the
10089// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100010090TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010092 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10093 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010095 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010096
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010097 ASSERT_TRUE(mDispatcher->waitForIdle());
10098 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010099}
10100
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010101// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
10102// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
10103TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
10104 const MotionEvent event =
10105 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
10106 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010107 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010108 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
10109 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010111 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010112 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
10113 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010114
10115 ASSERT_TRUE(mDispatcher->waitForIdle());
10116 mFakePolicy->assertOnPointerDownWasNotCalled();
10117 // Ensure that the unfocused window did not receive any FOCUS events.
10118 mUnfocusedWindow->assertNoEvents();
10119}
10120
chaviwaf87b3e2019-10-01 16:59:28 -070010121// These tests ensures we can send touch events to a single client when there are multiple input
10122// windows that point to the same client token.
10123class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
10124 virtual void SetUp() override {
10125 InputDispatcherTest::SetUp();
10126
Chris Yea209fde2020-07-22 13:54:51 -070010127 std::shared_ptr<FakeApplicationHandle> application =
10128 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010129 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010130 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -070010131 mWindow1->setFrame(Rect(0, 0, 100, 100));
10132
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010133 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -070010134 mWindow2->setFrame(Rect(100, 100, 200, 200));
10135
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010136 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -070010137 }
10138
10139protected:
10140 sp<FakeWindowHandle> mWindow1;
10141 sp<FakeWindowHandle> mWindow2;
10142
10143 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -050010144 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -070010145 vec2 vals = windowInfo->transform.transform(point.x, point.y);
10146 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -070010147 }
10148
10149 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
10150 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +010010151 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010152 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010153 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010154 ASSERT_NE(nullptr, motionEvent);
10155 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -070010156
10157 for (size_t i = 0; i < points.size(); i++) {
10158 float expectedX = points[i].x;
10159 float expectedY = points[i].y;
10160
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010161 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -070010162 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010163 << ", got " << motionEvent->getX(i);
10164 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -070010165 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010166 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -070010167 }
10168 }
chaviw9eaa22c2020-07-01 16:21:27 -070010169
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010170 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
10171 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -070010172 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010173 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010174 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -070010175
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010176 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010177 }
chaviwaf87b3e2019-10-01 16:59:28 -070010178};
10179
10180TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
10181 // Touch Window 1
10182 PointF touchedPoint = {10, 10};
10183 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010184 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010185
10186 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010187 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010188
10189 // Touch Window 2
10190 touchedPoint = {150, 150};
10191 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010192 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010193}
10194
chaviw9eaa22c2020-07-01 16:21:27 -070010195TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
10196 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -070010197 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010198 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -070010199
10200 // Touch Window 1
10201 PointF touchedPoint = {10, 10};
10202 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010203 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010204 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010205 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010206
10207 // Touch Window 2
10208 touchedPoint = {150, 150};
10209 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010210 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10211 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010212
chaviw9eaa22c2020-07-01 16:21:27 -070010213 // Update the transform so rotation is set
10214 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010215 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010216 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010217 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010218}
10219
chaviw9eaa22c2020-07-01 16:21:27 -070010220TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010221 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010222 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010223
10224 // Touch Window 1
10225 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10226 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010227 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010228
10229 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010230 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
10231 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
10232 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -070010233 touchedPoints.push_back(PointF{150, 150});
10234 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010235 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010236
chaviw9eaa22c2020-07-01 16:21:27 -070010237 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010238 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010239 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010240
chaviw9eaa22c2020-07-01 16:21:27 -070010241 // Update the transform so rotation is set for Window 2
10242 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010243 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010244 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010245 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010246}
10247
chaviw9eaa22c2020-07-01 16:21:27 -070010248TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010249 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010250 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010251
10252 // Touch Window 1
10253 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10254 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010255 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010256
10257 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -070010258 touchedPoints.push_back(PointF{150, 150});
10259 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010260
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010261 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010262
10263 // Move both windows
10264 touchedPoints = {{20, 20}, {175, 175}};
10265 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10266 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10267
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010268 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010269
chaviw9eaa22c2020-07-01 16:21:27 -070010270 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010271 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010272 expectedPoints.pop_back();
10273
10274 // Touch Window 2
10275 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010276 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010277 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010278 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010279
10280 // Move both windows
10281 touchedPoints = {{20, 20}, {175, 175}};
10282 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10283 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10284
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010285 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010286}
10287
10288TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
10289 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010290 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010291
10292 // Touch Window 1
10293 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10294 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010295 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010296
10297 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -070010298 touchedPoints.push_back(PointF{150, 150});
10299 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010300
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010301 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010302
10303 // Move both windows
10304 touchedPoints = {{20, 20}, {175, 175}};
10305 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10306 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10307
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010308 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010309}
10310
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010311/**
10312 * When one of the windows is slippery, the touch should not slip into the other window with the
10313 * same input channel.
10314 */
10315TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
10316 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010317 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010318
10319 // Touch down in window 1
10320 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010321 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010322 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
10323
10324 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
10325 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
10326 // getting generated.
10327 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010328 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010329
10330 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
10331}
10332
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010333/**
10334 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
10335 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
10336 * that the pointer is hovering over may have a different transform.
10337 */
10338TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010339 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010340
10341 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
10343 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10344 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010345 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
10346 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010347 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10349 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10350 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010351 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010352 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010353 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
10354}
10355
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010356class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
10357 virtual void SetUp() override {
10358 InputDispatcherTest::SetUp();
10359
Chris Yea209fde2020-07-22 13:54:51 -070010360 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010361 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010362 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010363 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010364 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010365 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -070010366 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010367
10368 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010369 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010370
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010371 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010372 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010373 mWindow->consumeFocusEvent(true);
10374 }
10375
10376 virtual void TearDown() override {
10377 InputDispatcherTest::TearDown();
10378 mWindow.clear();
10379 }
10380
10381protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010382 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -070010383 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010384 sp<FakeWindowHandle> mWindow;
10385 static constexpr PointF WINDOW_LOCATION = {20, 20};
10386
10387 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010388 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
10389 .x(WINDOW_LOCATION.x)
10390 .y(WINDOW_LOCATION.y);
10391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10392 .pointer(touchingPointer)
10393 .build());
10394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10395 .pointer(touchingPointer)
10396 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010397 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010398
10399 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010400 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
10401 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010402 spy->setTrustedOverlay(true);
10403 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010404 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010405 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010406 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010407 return spy;
10408 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010409};
10410
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010411// Send a tap and respond, which should not cause an ANR.
10412TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
10413 tapOnWindow();
10414 mWindow->consumeMotionDown();
10415 mWindow->consumeMotionUp();
10416 ASSERT_TRUE(mDispatcher->waitForIdle());
10417 mFakePolicy->assertNotifyAnrWasNotCalled();
10418}
10419
10420// Send a regular key and respond, which should not cause an ANR.
10421TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010423 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010424 ASSERT_TRUE(mDispatcher->waitForIdle());
10425 mFakePolicy->assertNotifyAnrWasNotCalled();
10426}
10427
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010428TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
10429 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010430 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010431 mWindow->consumeFocusEvent(false);
10432
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010433 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010434 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10435 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
10436 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +000010437 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010439 // Key will not go to window because we have no focused window.
10440 // The 'no focused window' ANR timer should start instead.
10441
10442 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010443 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010444 // The key should get dropped and there should be no ANR.
10445
10446 ASSERT_TRUE(mDispatcher->waitForIdle());
10447 mFakePolicy->assertNotifyAnrWasNotCalled();
10448}
10449
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010450// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010451// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10452// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010453TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010455 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10456 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010457
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010458 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010459 ASSERT_TRUE(sequenceNum);
10460 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010461 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010462
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010463 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010464 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010465 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010466 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010467 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010468}
10469
10470// Send a key to the app and have the app not respond right away.
10471TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
10472 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010474 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010475 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010476 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010477 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010478 ASSERT_TRUE(mDispatcher->waitForIdle());
10479}
10480
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010481// We have a focused application, but no focused window
10482TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010483 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010484 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010485 mWindow->consumeFocusEvent(false);
10486
10487 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010489 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10490 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010491 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10492 mDispatcher->waitForIdle();
10493 mFakePolicy->assertNotifyAnrWasNotCalled();
10494
10495 // Once a focused event arrives, we get an ANR for this application
10496 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10497 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010498 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010499 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10500 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +080010501 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010502 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010503 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -070010504 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010505 ASSERT_TRUE(mDispatcher->waitForIdle());
10506}
10507
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010508/**
10509 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
10510 * there will not be an ANR.
10511 */
10512TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
10513 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010514 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010515 mWindow->consumeFocusEvent(false);
10516
10517 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -070010518 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
10519 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010520 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
10521 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
10522
10523 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010524 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
10525 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
10526 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
10527 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010528
Hu Guofe3c8f12023-09-22 17:20:15 +080010529 const int32_t policyFlags =
10530 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010531
10532 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +000010533 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010534 InputEventInjectionSync::WAIT_FOR_RESULT,
10535 INJECT_EVENT_TIMEOUT, policyFlags);
10536 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
10537 << "Injection should fail because the event is stale";
10538
10539 ASSERT_TRUE(mDispatcher->waitForIdle());
10540 mFakePolicy->assertNotifyAnrWasNotCalled();
10541 mWindow->assertNoEvents();
10542}
10543
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010544// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010545// Make sure that we don't notify policy twice about the same ANR.
10546TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010547 const std::chrono::duration appTimeout = 400ms;
10548 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010549 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010550
Vishnu Nair47074b82020-08-14 11:54:47 -070010551 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010552 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010553 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010554
10555 // Once a focused event arrives, we get an ANR for this application
10556 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10557 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010558 const std::chrono::duration eventInjectionTimeout = 100ms;
10559 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010560 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010561 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10562 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
10563 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010564 /*allowKeyRepeat=*/false);
10565 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
10566 << "result=" << ftl::enum_string(result);
10567 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
10568 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
10569 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
10570 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010571
Vishnu Naire4df8752022-09-08 09:17:55 -070010572 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010573 // ANR should not be raised again. It is up to policy to do that if it desires.
10574 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010575
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010576 // If we now get a focused window, the ANR should stop, but the policy handles that via
10577 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010578 ASSERT_TRUE(mDispatcher->waitForIdle());
10579}
10580
10581// We have a focused application, but no focused window
10582TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010583 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010584 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010585 mWindow->consumeFocusEvent(false);
10586
10587 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010588 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010589
Vishnu Naire4df8752022-09-08 09:17:55 -070010590 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10591 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010592
10593 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010594 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010595 ASSERT_TRUE(mDispatcher->waitForIdle());
10596 mWindow->assertNoEvents();
10597}
10598
10599/**
10600 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
10601 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
10602 * If we process 1 of the events, but ANR on the second event with the same timestamp,
10603 * the ANR mechanism should still work.
10604 *
10605 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
10606 * DOWN event, while not responding on the second one.
10607 */
10608TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
10609 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010610 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010611 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010612 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10613 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010614 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010615
10616 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010617 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010618 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010619 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10620 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010621 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010622
10623 // 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 -070010624 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010625 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010626 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010627}
10628
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010629// A spy window can receive an ANR
10630TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
10631 sp<FakeWindowHandle> spy = addSpyWindow();
10632
10633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010634 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10635 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010636 mWindow->consumeMotionDown();
10637
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010638 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010639 ASSERT_TRUE(sequenceNum);
10640 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010641 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010642
10643 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010644 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010645 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010646 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010647 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010648}
10649
10650// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010651// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010652TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10653 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010654
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010656 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10657 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10659 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010660
10661 // Stuck on the ACTION_UP
10662 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010663 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010664
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010665 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010666 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010667 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10668 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010669
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010670 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010671 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010672 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010673 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010674 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010675}
10676
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010677// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010678// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010679TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10680 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010681
10682 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010683 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10684 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010685
10686 mWindow->consumeMotionDown();
10687 // Stuck on the ACTION_UP
10688 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010689 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010690
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010691 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010692 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010693 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10694 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010695
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010696 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010697 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010698 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010699 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010700 spy->assertNoEvents();
10701}
10702
10703TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010704 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010705
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010706 FakeMonitorReceiver monitor =
10707 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010708
10709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010710 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10711 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010712
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010713 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010714 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10715 ASSERT_TRUE(consumeSeq);
10716
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010717 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10718 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010719
10720 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010721 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010722
10723 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010724 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010725}
10726
10727// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10728// process events, you don't get an anr. When the window later becomes unresponsive again, you
10729// get an ANR again.
10730// 1. tap -> block on ACTION_UP -> receive ANR
10731// 2. consume all pending events (= queue becomes healthy again)
10732// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10733TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10734 tapOnWindow();
10735
10736 mWindow->consumeMotionDown();
10737 // Block on ACTION_UP
10738 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010739 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010740 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10741 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010742 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010743 mWindow->assertNoEvents();
10744
10745 tapOnWindow();
10746 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010747 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010748 mWindow->consumeMotionUp();
10749
10750 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010751 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010752 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010753 mWindow->assertNoEvents();
10754}
10755
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010756// If a connection remains unresponsive for a while, make sure policy is only notified once about
10757// it.
10758TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10761 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010762
10763 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010764 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010765 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010766 // 'notifyConnectionUnresponsive' should only be called once per connection
10767 mFakePolicy->assertNotifyAnrWasNotCalled();
10768 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010769 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010770 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010771 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010772 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010773 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010774 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010775 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010776}
10777
10778/**
10779 * 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 -070010780 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010781 */
10782TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010783 // The timeouts in this test are established by relying on the fact that the "key waiting for
10784 // events timeout" is equal to 500ms.
10785 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010786 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010787 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010788
10789 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010790 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010791 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010792 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010793 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010794
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010795 // Don't finish the events yet, and send a key
10796 mDispatcher->notifyKey(
10797 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10798 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10799 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010800 // Key will not be sent to the window, yet, because the window is still processing events
10801 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010802 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010803 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010804
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010805 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010806 // if we wait long enough though, dispatcher will give up, and still send the key
10807 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010808 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010809 mWindow->finishEvent(*downSequenceNum);
10810 mWindow->finishEvent(*upSequenceNum);
10811}
10812
10813/**
10814 * If a window is processing a motion event, and then a key event comes in, the key event should
10815 * not go to the focused window until the motion is processed.
10816 * If then a new motion comes in, then the pending key event should be going to the currently
10817 * focused window right away.
10818 */
10819TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010820 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10821 // The timeouts in this test are established by relying on the fact that the "key waiting for
10822 // events timeout" is equal to 500ms.
10823 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010824 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010825 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010826
10827 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010828 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010829 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010830 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010831 ASSERT_TRUE(upSequenceNum);
10832 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010833 mDispatcher->notifyKey(
10834 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10835 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10836 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010837 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010838 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010839
10840 // Now tap down again. It should cause the pending key to go to the focused window right away.
10841 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010842 // Now that we tapped, we should receive the key immediately.
10843 // Since there's still room for slowness, we use 200ms, which is much less than
10844 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10845 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10846 ASSERT_NE(nullptr, keyEvent);
10847 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10848 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10849 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10850 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010851 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10852 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010853 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10854 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010855 mWindow->assertNoEvents();
10856}
10857
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010858/**
10859 * Send an event to the app and have the app not respond right away.
10860 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10861 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10862 * At some point, the window becomes responsive again.
10863 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10864 */
10865TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10866 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10867 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10868 .build());
10869
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010870 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010871 ASSERT_TRUE(sequenceNum);
10872 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10873 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10874
10875 mWindow->finishEvent(*sequenceNum);
10876 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10877 ASSERT_TRUE(mDispatcher->waitForIdle());
10878 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10879
10880 // Now that the window is responsive, let's continue the gesture.
10881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10882 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10883 .build());
10884
10885 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10886 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10887 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10888 .build());
10889
10890 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10891 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10892 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10893 .build());
10894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10895 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10896 .build());
10897 // We already canceled this pointer, so the window shouldn't get any new events.
10898 mWindow->assertNoEvents();
10899
10900 // Start another one.
10901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10902 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10903 .build());
10904 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10905}
10906
Prabir Pradhanfc364722024-02-08 17:51:20 +000010907// Send an event to the app and have the app not respond right away. Then remove the app window.
10908// When the window is removed, the dispatcher will cancel the events for that window.
10909// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10910TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10911 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010912 AINPUT_SOURCE_TOUCHSCREEN,
10913 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010914
10915 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10916 ASSERT_TRUE(sequenceNum);
10917
10918 // Remove the window, but the input channel should remain alive.
10919 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10920
10921 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10922 // Since the window was removed, Dispatcher does not know the PID associated with the window
10923 // anymore, so the policy is notified without the PID.
10924 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10925 /*pid=*/std::nullopt);
10926
10927 mWindow->finishEvent(*sequenceNum);
10928 // The cancellation was generated when the window was removed, along with the focus event.
10929 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010930 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010931 mWindow->consumeFocusEvent(false);
10932 ASSERT_TRUE(mDispatcher->waitForIdle());
10933 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10934}
10935
10936// Send an event to the app and have the app not respond right away. Wait for the policy to be
10937// notified of the unresponsive window, then remove the app window.
10938TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10939 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010940 AINPUT_SOURCE_TOUCHSCREEN,
10941 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010942
10943 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10944 ASSERT_TRUE(sequenceNum);
10945 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10946 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10947
10948 // Remove the window, but the input channel should remain alive.
10949 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10950
10951 mWindow->finishEvent(*sequenceNum);
10952 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10953 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010954 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010955 mWindow->consumeFocusEvent(false);
10956 ASSERT_TRUE(mDispatcher->waitForIdle());
10957 // Since the window was removed, Dispatcher does not know the PID associated with the window
10958 // becoming responsive, so the policy is notified without the PID.
10959 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10960}
10961
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010962class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10963 virtual void SetUp() override {
10964 InputDispatcherTest::SetUp();
10965
Chris Yea209fde2020-07-22 13:54:51 -070010966 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010967 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010968 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010969 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010970 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010971 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010972 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010973
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010974 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010975 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010976 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010977 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010978
10979 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010980 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010981 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010982
10983 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010984 mDispatcher->onWindowInfosChanged(
10985 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010986 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010987 mFocusedWindow->consumeFocusEvent(true);
10988 }
10989
10990 virtual void TearDown() override {
10991 InputDispatcherTest::TearDown();
10992
10993 mUnfocusedWindow.clear();
10994 mFocusedWindow.clear();
10995 }
10996
10997protected:
Chris Yea209fde2020-07-22 13:54:51 -070010998 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010999 sp<FakeWindowHandle> mUnfocusedWindow;
11000 sp<FakeWindowHandle> mFocusedWindow;
11001 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
11002 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
11003 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
11004
11005 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
11006
11007 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
11008
11009private:
11010 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011012 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11013 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011015 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11016 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011017 }
11018};
11019
11020// If we have 2 windows that are both unresponsive, the one with the shortest timeout
11021// should be ANR'd first.
11022TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011024 injectMotionEvent(*mDispatcher,
11025 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11026 AINPUT_SOURCE_TOUCHSCREEN)
11027 .pointer(PointerBuilder(0, ToolType::FINGER)
11028 .x(FOCUSED_WINDOW_LOCATION.x)
11029 .y(FOCUSED_WINDOW_LOCATION.y))
11030 .build()));
11031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11032 injectMotionEvent(*mDispatcher,
11033 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
11034 AINPUT_SOURCE_TOUCHSCREEN)
11035 .pointer(PointerBuilder(0, ToolType::FINGER)
11036 .x(FOCUSED_WINDOW_LOCATION.x)
11037 .y(FOCUSED_WINDOW_LOCATION.y))
11038 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011039 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011040 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011041 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011042 // We consumed all events, so no ANR
11043 ASSERT_TRUE(mDispatcher->waitForIdle());
11044 mFakePolicy->assertNotifyAnrWasNotCalled();
11045
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011047 injectMotionEvent(*mDispatcher,
11048 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11049 AINPUT_SOURCE_TOUCHSCREEN)
11050 .pointer(PointerBuilder(0, ToolType::FINGER)
11051 .x(FOCUSED_WINDOW_LOCATION.x)
11052 .y(FOCUSED_WINDOW_LOCATION.y))
11053 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011054 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011055 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011056
11057 const std::chrono::duration timeout =
11058 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011059 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011060
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011061 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011062 mFocusedWindow->consumeMotionDown();
11063 // This cancel is generated because the connection was unresponsive
11064 mFocusedWindow->consumeMotionCancel();
11065 mFocusedWindow->assertNoEvents();
11066 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011067 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080011068 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11069 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011070 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011071}
11072
11073// If we have 2 windows with identical timeouts that are both unresponsive,
11074// it doesn't matter which order they should have ANR.
11075// But we should receive ANR for both.
11076TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
11077 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011078 mUnfocusedWindow->setDispatchingTimeout(
11079 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011080 mDispatcher->onWindowInfosChanged(
11081 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011082
11083 tapOnFocusedWindow();
11084 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011085 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011086 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
11087 mFocusedWindow->getDispatchingTimeout(
11088 DISPATCHING_TIMEOUT)),
11089 mFakePolicy->getUnresponsiveWindowToken(0ms)};
11090
11091 ASSERT_THAT(anrConnectionTokens,
11092 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11093 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011094
11095 ASSERT_TRUE(mDispatcher->waitForIdle());
11096 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011097
11098 mFocusedWindow->consumeMotionDown();
11099 mFocusedWindow->consumeMotionUp();
11100 mUnfocusedWindow->consumeMotionOutside();
11101
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011102 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
11103 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011104
11105 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011106 ASSERT_THAT(responsiveTokens,
11107 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11108 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011109 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011110}
11111
11112// If a window is already not responding, the second tap on the same window should be ignored.
11113// We should also log an error to account for the dropped event (not tested here).
11114// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
11115TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
11116 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011117 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011118 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011119 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011120 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011121 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011122 ASSERT_TRUE(upEventSequenceNum);
11123 const std::chrono::duration timeout =
11124 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011125 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011126
11127 // Tap once again
11128 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011129 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011130 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11131 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011132 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011133 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011134 FOCUSED_WINDOW_LOCATION));
11135 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
11136 // valid touch target
11137 mUnfocusedWindow->assertNoEvents();
11138
11139 // Consume the first tap
11140 mFocusedWindow->finishEvent(*downEventSequenceNum);
11141 mFocusedWindow->finishEvent(*upEventSequenceNum);
11142 ASSERT_TRUE(mDispatcher->waitForIdle());
11143 // The second tap did not go to the focused window
11144 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011145 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080011146 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11147 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011148 mFakePolicy->assertNotifyAnrWasNotCalled();
11149}
11150
11151// If you tap outside of all windows, there will not be ANR
11152TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011153 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011154 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11155 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011156 ASSERT_TRUE(mDispatcher->waitForIdle());
11157 mFakePolicy->assertNotifyAnrWasNotCalled();
11158}
11159
11160// Since the focused window is paused, tapping on it should not produce any events
11161TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
11162 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011163 mDispatcher->onWindowInfosChanged(
11164 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011165
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011166 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011167 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11168 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011169
11170 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
11171 ASSERT_TRUE(mDispatcher->waitForIdle());
11172 // Should not ANR because the window is paused, and touches shouldn't go to it
11173 mFakePolicy->assertNotifyAnrWasNotCalled();
11174
11175 mFocusedWindow->assertNoEvents();
11176 mUnfocusedWindow->assertNoEvents();
11177}
11178
11179/**
11180 * 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 -070011181 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011182 * If a different window becomes focused at this time, the key should go to that window instead.
11183 *
11184 * Warning!!!
11185 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
11186 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011187 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011188 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
11189 *
11190 * If that value changes, this test should also change.
11191 */
11192TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
11193 // Set a long ANR timeout to prevent it from triggering
11194 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011195 mDispatcher->onWindowInfosChanged(
11196 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011197
11198 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011199 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011200 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011201 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011202 ASSERT_TRUE(upSequenceNum);
11203 // Don't finish the events yet, and send a key
11204 // Injection will succeed because we will eventually give up and send the key to the focused
11205 // window even if motions are still being processed.
11206
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011207 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011208 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11209 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011210 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011212 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011213 // and the key remains pending, waiting for the touch events to be processed.
11214 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
11215 // under the hood.
11216 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
11217 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011218
11219 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070011220 mFocusedWindow->setFocusable(false);
11221 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011222 mDispatcher->onWindowInfosChanged(
11223 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011224 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011225
11226 // Focus events should precede the key events
11227 mUnfocusedWindow->consumeFocusEvent(true);
11228 mFocusedWindow->consumeFocusEvent(false);
11229
11230 // Finish the tap events, which should unblock dispatcher
11231 mUnfocusedWindow->finishEvent(*downSequenceNum);
11232 mUnfocusedWindow->finishEvent(*upSequenceNum);
11233
11234 // Now that all queues are cleared and no backlog in the connections, the key event
11235 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011236 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011237 mFocusedWindow->assertNoEvents();
11238 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011239 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011240}
11241
11242// When the touch stream is split across 2 windows, and one of them does not respond,
11243// then ANR should be raised and the touch should be canceled for the unresponsive window.
11244// The other window should not be affected by that.
11245TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
11246 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011247 mDispatcher->notifyMotion(
11248 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11249 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
11250 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011251
11252 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000011253 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011254 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11255 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011256 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011257
11258 const std::chrono::duration timeout =
11259 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011260 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011261
11262 mUnfocusedWindow->consumeMotionDown();
11263 mFocusedWindow->consumeMotionDown();
11264 // Focused window may or may not receive ACTION_MOVE
11265 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011266 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011267 ASSERT_TRUE(moveOrCancelSequenceNum);
11268 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
11269 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070011270 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011271 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
11272 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
11273 mFocusedWindow->consumeMotionCancel();
11274 } else {
11275 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
11276 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011277 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080011278 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11279 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011280
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011281 mUnfocusedWindow->assertNoEvents();
11282 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011283 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011284}
11285
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011286/**
11287 * If we have no focused window, and a key comes in, we start the ANR timer.
11288 * The focused application should add a focused window before the timer runs out to prevent ANR.
11289 *
11290 * If the user touches another application during this time, the key should be dropped.
11291 * Next, if a new focused window comes in, without toggling the focused application,
11292 * then no ANR should occur.
11293 *
11294 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
11295 * but in some cases the policy may not update the focused application.
11296 */
11297TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
11298 std::shared_ptr<FakeApplicationHandle> focusedApplication =
11299 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070011300 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011301 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011302 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
11303 mFocusedWindow->setFocusable(false);
11304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011305 mDispatcher->onWindowInfosChanged(
11306 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011307 mFocusedWindow->consumeFocusEvent(false);
11308
11309 // Send a key. The ANR timer should start because there is no focused window.
11310 // 'focusedApplication' will get blamed if this timer completes.
11311 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011312 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011313 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11314 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011315 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000011316 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011318
11319 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
11320 // then the injected touches won't cause the focused event to get dropped.
11321 // The dispatcher only checks for whether the queue should be pruned upon queueing.
11322 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
11323 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
11324 // For this test, it means that the key would get delivered to the window once it becomes
11325 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011326 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011327
11328 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011329 mDispatcher->notifyMotion(
11330 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11331 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011332
11333 // We do not consume the motion right away, because that would require dispatcher to first
11334 // process (== drop) the key event, and by that time, ANR will be raised.
11335 // Set the focused window first.
11336 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011337 mDispatcher->onWindowInfosChanged(
11338 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011339 setFocusedWindow(mFocusedWindow);
11340 mFocusedWindow->consumeFocusEvent(true);
11341 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
11342 // to another application. This could be a bug / behaviour in the policy.
11343
11344 mUnfocusedWindow->consumeMotionDown();
11345
11346 ASSERT_TRUE(mDispatcher->waitForIdle());
11347 // Should not ANR because we actually have a focused window. It was just added too slowly.
11348 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
11349}
11350
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011351/**
11352 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
11353 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
11354 * dispatcher doesn't prune pointer events incorrectly.
11355 *
11356 * This test reproduces a crash in InputDispatcher.
11357 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
11358 *
11359 * Keep the currently focused application (mApplication), and have no focused window.
11360 * We set up two additional windows:
11361 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
11362 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
11363 * window. This window is not focusable, but is touchable.
11364 *
11365 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
11366 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
11367 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
11368 *
11369 * Now, we touch "Another window". This window is owned by a different application than
11370 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
11371 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
11372 * dropping the events from its queue. Ensure that no crash occurs.
11373 *
11374 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
11375 * This does not affect the test running time.
11376 */
11377TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
11378 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
11379 std::make_shared<FakeApplicationHandle>();
11380 systemUiApplication->setDispatchingTimeout(3000ms);
11381 mFakePolicy->setStaleEventTimeout(3000ms);
11382 sp<FakeWindowHandle> navigationBar =
11383 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011384 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011385 navigationBar->setFocusable(false);
11386 navigationBar->setWatchOutsideTouch(true);
11387 navigationBar->setFrame(Rect(0, 0, 100, 100));
11388
11389 mApplication->setDispatchingTimeout(3000ms);
11390 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011391 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011392
11393 std::shared_ptr<FakeApplicationHandle> anotherApplication =
11394 std::make_shared<FakeApplicationHandle>();
11395 sp<FakeWindowHandle> appWindow =
11396 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011397 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011398 appWindow->setFocusable(false);
11399 appWindow->setFrame(Rect(100, 100, 200, 200));
11400
11401 mDispatcher->onWindowInfosChanged(
11402 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
11403 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
11404 mFocusedWindow->consumeFocusEvent(false);
11405
11406 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
11407 // in response.
11408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11409 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11410 .build());
11411 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11412
11413 // Key will not be sent anywhere because we have no focused window. It will remain pending.
11414 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
11415 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011416 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11417 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011418 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011419 /*allowKeyRepeat=*/false);
11420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11421
11422 // Finish the gesture - lift up finger and inject ACTION_UP key event
11423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11424 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11425 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011426 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
11427 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011428 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011429 /*allowKeyRepeat=*/false);
11430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11431 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
11432 // getting any events yet.
11433 navigationBar->assertNoEvents();
11434
11435 // Now touch "Another window". This touch is going to a different application than the one we
11436 // are waiting for (which is 'mApplication').
11437 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
11438 // trying to be injected) and to continue processing the rest of the events in the original
11439 // order.
11440 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11441 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
11442 .build());
11443 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
11444 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
11445 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11446
11447 appWindow->assertNoEvents();
11448 navigationBar->assertNoEvents();
11449}
11450
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011451// These tests ensure we cannot send touch events to a window that's positioned behind a window
11452// that has feature NO_INPUT_CHANNEL.
11453// Layout:
11454// Top (closest to user)
11455// mNoInputWindow (above all windows)
11456// mBottomWindow
11457// Bottom (furthest from user)
11458class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
11459 virtual void SetUp() override {
11460 InputDispatcherTest::SetUp();
11461
11462 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011463 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11464 "Window without input channel",
11465 ui::LogicalDisplayId::DEFAULT,
11466 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011467 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011468 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
11469 // It's perfectly valid for this window to not have an associated input channel
11470
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011471 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011472 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011473 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
11474
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011475 mDispatcher->onWindowInfosChanged(
11476 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011477 }
11478
11479protected:
11480 std::shared_ptr<FakeApplicationHandle> mApplication;
11481 sp<FakeWindowHandle> mNoInputWindow;
11482 sp<FakeWindowHandle> mBottomWindow;
11483};
11484
11485TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
11486 PointF touchedPoint = {10, 10};
11487
Prabir Pradhan678438e2023-04-13 19:32:51 +000011488 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011489 AINPUT_SOURCE_TOUCHSCREEN,
11490 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011491
11492 mNoInputWindow->assertNoEvents();
11493 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
11494 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
11495 // and therefore should prevent mBottomWindow from receiving touches
11496 mBottomWindow->assertNoEvents();
11497}
11498
11499/**
11500 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
11501 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
11502 */
11503TEST_F(InputDispatcherMultiWindowOcclusionTests,
11504 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011505 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11506 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011507 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011508
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011509 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011510 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011511 mDispatcher->onWindowInfosChanged(
11512 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011513
11514 PointF touchedPoint = {10, 10};
11515
Prabir Pradhan678438e2023-04-13 19:32:51 +000011516 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011517 AINPUT_SOURCE_TOUCHSCREEN,
11518 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011519
11520 mNoInputWindow->assertNoEvents();
11521 mBottomWindow->assertNoEvents();
11522}
11523
Vishnu Nair958da932020-08-21 17:12:37 -070011524class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
11525protected:
11526 std::shared_ptr<FakeApplicationHandle> mApp;
11527 sp<FakeWindowHandle> mWindow;
11528 sp<FakeWindowHandle> mMirror;
11529
11530 virtual void SetUp() override {
11531 InputDispatcherTest::SetUp();
11532 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011533 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11534 ui::LogicalDisplayId::DEFAULT);
11535 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
11536 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070011537 mWindow->setFocusable(true);
11538 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011539 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011540 }
11541};
11542
11543TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
11544 // Request focus on a mirrored window
11545 setFocusedWindow(mMirror);
11546
11547 // window gets focused
11548 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011550 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011551 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011552}
11553
11554// A focused & mirrored window remains focused only if the window and its mirror are both
11555// focusable.
11556TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
11557 setFocusedWindow(mMirror);
11558
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000011559 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070011560 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011562 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011563 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011565 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011566 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011567
11568 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011569 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011570
11571 // window loses focus since one of the windows associated with the token in not focusable
11572 mWindow->consumeFocusEvent(false);
11573
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011574 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011575 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011576 mWindow->assertNoEvents();
11577}
11578
11579// A focused & mirrored window remains focused until the window and its mirror both become
11580// invisible.
11581TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
11582 setFocusedWindow(mMirror);
11583
11584 // window gets focused
11585 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011587 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011588 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011590 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011591 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011592
11593 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011594 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011595
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011597 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011598 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011600 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011601 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011602
11603 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011604 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011605
11606 // window loses focus only after all windows associated with the token become invisible.
11607 mWindow->consumeFocusEvent(false);
11608
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011609 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011610 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011611 mWindow->assertNoEvents();
11612}
11613
11614// A focused & mirrored window remains focused until both windows are removed.
11615TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
11616 setFocusedWindow(mMirror);
11617
11618 // window gets focused
11619 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011621 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011622 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011624 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011625 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011626
11627 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011628 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011629
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011631 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011632 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011634 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011635 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011636
11637 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011638 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011639 mWindow->consumeFocusEvent(false);
11640
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011641 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011642 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011643 mWindow->assertNoEvents();
11644}
11645
11646// Focus request can be pending until one window becomes visible.
11647TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11648 // Request focus on an invisible mirror.
11649 mWindow->setVisible(false);
11650 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011651 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011652 setFocusedWindow(mMirror);
11653
11654 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011656 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011657 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070011658
11659 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011660 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011661
11662 // window gets focused
11663 mWindow->consumeFocusEvent(true);
11664 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011665 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070011666}
Prabir Pradhan99987712020-11-10 18:43:05 -080011667
11668class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11669protected:
11670 std::shared_ptr<FakeApplicationHandle> mApp;
11671 sp<FakeWindowHandle> mWindow;
11672 sp<FakeWindowHandle> mSecondWindow;
11673
11674 void SetUp() override {
11675 InputDispatcherTest::SetUp();
11676 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011677 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11678 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011679 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011680 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11681 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011682 mSecondWindow->setFocusable(true);
11683
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011684 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011685 mDispatcher->onWindowInfosChanged(
11686 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080011687
11688 setFocusedWindow(mWindow);
11689 mWindow->consumeFocusEvent(true);
11690 }
11691
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011692 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011693 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011694 }
11695
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011696 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11697 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011698 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011699 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011700 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011701 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011702 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011703 }
11704};
11705
11706TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11707 // Ensure that capture cannot be obtained for unfocused windows.
11708 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11709 mFakePolicy->assertSetPointerCaptureNotCalled();
11710 mSecondWindow->assertNoEvents();
11711
11712 // Ensure that capture can be enabled from the focus window.
11713 requestAndVerifyPointerCapture(mWindow, true);
11714
11715 // Ensure that capture cannot be disabled from a window that does not have capture.
11716 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11717 mFakePolicy->assertSetPointerCaptureNotCalled();
11718
11719 // Ensure that capture can be disabled from the window with capture.
11720 requestAndVerifyPointerCapture(mWindow, false);
11721}
11722
11723TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011724 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011725
11726 setFocusedWindow(mSecondWindow);
11727
11728 // Ensure that the capture disabled event was sent first.
11729 mWindow->consumeCaptureEvent(false);
11730 mWindow->consumeFocusEvent(false);
11731 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011732 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011733
11734 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011735 notifyPointerCaptureChanged({});
11736 notifyPointerCaptureChanged(request);
11737 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011738 mWindow->assertNoEvents();
11739 mSecondWindow->assertNoEvents();
11740 mFakePolicy->assertSetPointerCaptureNotCalled();
11741}
11742
11743TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011744 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011745
11746 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011747 notifyPointerCaptureChanged({});
11748 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011749
11750 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011751 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011752 mWindow->consumeCaptureEvent(false);
11753 mWindow->assertNoEvents();
11754}
11755
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011756TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11757 requestAndVerifyPointerCapture(mWindow, true);
11758
11759 // The first window loses focus.
11760 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011761 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011762 mWindow->consumeCaptureEvent(false);
11763
11764 // Request Pointer Capture from the second window before the notification from InputReader
11765 // arrives.
11766 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011767 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011768
11769 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011770 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011771
11772 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011773 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011774
11775 mSecondWindow->consumeFocusEvent(true);
11776 mSecondWindow->consumeCaptureEvent(true);
11777}
11778
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011779TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11780 // App repeatedly enables and disables capture.
11781 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011782 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011783 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011784 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011785 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011786 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011787
11788 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11789 // first request is now stale, this should do nothing.
11790 notifyPointerCaptureChanged(firstRequest);
11791 mWindow->assertNoEvents();
11792
11793 // InputReader notifies that the second request was enabled.
11794 notifyPointerCaptureChanged(secondRequest);
11795 mWindow->consumeCaptureEvent(true);
11796}
11797
Prabir Pradhan7092e262022-05-03 16:51:09 +000011798TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11799 requestAndVerifyPointerCapture(mWindow, true);
11800
11801 // App toggles pointer capture off and on.
11802 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011803 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011804
11805 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011806 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011807
11808 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11809 // preceding "disable" request.
11810 notifyPointerCaptureChanged(enableRequest);
11811
11812 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11813 // any notifications.
11814 mWindow->assertNoEvents();
11815}
11816
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011817/**
11818 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11819 * mouse movements don't affect the previous mouse hovering state.
11820 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11821 * HOVER_MOVE events).
11822 */
11823TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11824 // Mouse hover on the window
11825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11826 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11827 .build());
11828 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11829 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11830 .build());
11831
11832 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11833 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11834
11835 // Start pointer capture
11836 requestAndVerifyPointerCapture(mWindow, true);
11837
11838 // Send some relative mouse movements and receive them in the window.
11839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11840 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11841 .build());
11842 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11843 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11844
11845 // Stop pointer capture
11846 requestAndVerifyPointerCapture(mWindow, false);
11847
11848 // Continue hovering on the window
11849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11850 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11851 .build());
11852 mWindow->consumeMotionEvent(
11853 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11854
11855 mWindow->assertNoEvents();
11856}
11857
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011858TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11859 // The default display is the focused display to begin with.
11860 requestAndVerifyPointerCapture(mWindow, true);
11861
11862 // Move the second window to a second display, make it the focused window on that display.
11863 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11864 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11865 setFocusedWindow(mSecondWindow);
11866 mSecondWindow->consumeFocusEvent(true);
11867
11868 mWindow->assertNoEvents();
11869
11870 // The second window cannot gain capture because it is not on the focused display.
11871 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11872 mFakePolicy->assertSetPointerCaptureNotCalled();
11873 mSecondWindow->assertNoEvents();
11874
11875 // Make the second display the focused display.
11876 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011877 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011878
11879 // This causes the first window to lose pointer capture, and it's unable to request capture.
11880 mWindow->consumeCaptureEvent(false);
11881 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11882
11883 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11884 mFakePolicy->assertSetPointerCaptureNotCalled();
11885
11886 // The second window is now able to gain pointer capture successfully.
11887 requestAndVerifyPointerCapture(mSecondWindow, true);
11888}
11889
Hiroki Sato25040232024-02-22 17:21:22 +090011890using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11891
11892TEST_F(InputDispatcherPointerCaptureDeathTest,
11893 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11894 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11895 ScopedSilentDeath _silentDeath;
11896
11897 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11898 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11899
11900 // Dispatch a pointer changed event with a wrong token.
11901 request.window = mSecondWindow->getToken();
11902 ASSERT_DEATH(
11903 {
11904 notifyPointerCaptureChanged(request);
11905 mSecondWindow->consumeCaptureEvent(true);
11906 },
11907 "Unexpected requested window for Pointer Capture.");
11908}
11909
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011910class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11911protected:
11912 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011913
11914 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11915 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11916
11917 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11918 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11919
11920 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11921 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11922 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11923 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11924 MAXIMUM_OBSCURING_OPACITY);
11925
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011926 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11927 static constexpr gui::Uid APP_B_UID{10002};
11928 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011929
11930 sp<FakeWindowHandle> mTouchWindow;
11931
11932 virtual void SetUp() override {
11933 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011934 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011935 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11936 }
11937
11938 virtual void TearDown() override {
11939 InputDispatcherTest::TearDown();
11940 mTouchWindow.clear();
11941 }
11942
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011943 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011944 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011945 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011946 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011947 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011948 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011949 return window;
11950 }
11951
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011952 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011953 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11954 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011955 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011956 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011957 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011958 return window;
11959 }
11960
11961 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011962 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011963 AINPUT_SOURCE_TOUCHSCREEN,
11964 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011965 }
11966};
11967
11968TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011969 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011970 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011971 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011972
11973 touch();
11974
11975 mTouchWindow->assertNoEvents();
11976}
11977
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011978TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011979 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11980 const sp<FakeWindowHandle>& w =
11981 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011982 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011983
11984 touch();
11985
11986 mTouchWindow->assertNoEvents();
11987}
11988
11989TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011990 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11991 const sp<FakeWindowHandle>& w =
11992 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011993 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011994
11995 touch();
11996
11997 w->assertNoEvents();
11998}
11999
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012000TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012001 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012002 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012003
12004 touch();
12005
12006 mTouchWindow->consumeAnyMotionDown();
12007}
12008
12009TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012010 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012011 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012012 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012013 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012014
12015 touch({PointF{100, 100}});
12016
12017 mTouchWindow->consumeAnyMotionDown();
12018}
12019
12020TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012021 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012022 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012023 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012024
12025 touch();
12026
12027 mTouchWindow->consumeAnyMotionDown();
12028}
12029
12030TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
12031 const sp<FakeWindowHandle>& w =
12032 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012033 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012034
12035 touch();
12036
12037 mTouchWindow->consumeAnyMotionDown();
12038}
12039
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012040TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
12041 const sp<FakeWindowHandle>& w =
12042 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012043 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012044
12045 touch();
12046
12047 w->assertNoEvents();
12048}
12049
12050/**
12051 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
12052 * inside) while letting them pass-through. Note that even though touch passes through the occluding
12053 * window, the occluding window will still receive ACTION_OUTSIDE event.
12054 */
12055TEST_F(InputDispatcherUntrustedTouchesTest,
12056 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
12057 const sp<FakeWindowHandle>& w =
12058 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012059 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012060 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012061
12062 touch();
12063
12064 w->consumeMotionOutside();
12065}
12066
12067TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
12068 const sp<FakeWindowHandle>& w =
12069 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012070 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012071 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012072
12073 touch();
12074
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012075 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012076}
12077
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012078TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012079 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012080 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12081 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012082 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012083
12084 touch();
12085
12086 mTouchWindow->consumeAnyMotionDown();
12087}
12088
12089TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
12090 const sp<FakeWindowHandle>& w =
12091 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12092 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012093 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012094
12095 touch();
12096
12097 mTouchWindow->consumeAnyMotionDown();
12098}
12099
12100TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012101 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012102 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12103 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012104 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012105
12106 touch();
12107
12108 mTouchWindow->assertNoEvents();
12109}
12110
12111TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
12112 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
12113 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012114 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12115 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012116 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012117 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12118 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012119 mDispatcher->onWindowInfosChanged(
12120 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012121
12122 touch();
12123
12124 mTouchWindow->assertNoEvents();
12125}
12126
12127TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
12128 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
12129 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012130 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12131 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012132 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012133 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12134 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012135 mDispatcher->onWindowInfosChanged(
12136 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012137
12138 touch();
12139
12140 mTouchWindow->consumeAnyMotionDown();
12141}
12142
12143TEST_F(InputDispatcherUntrustedTouchesTest,
12144 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
12145 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012146 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12147 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012148 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012149 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12150 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012151 mDispatcher->onWindowInfosChanged(
12152 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012153
12154 touch();
12155
12156 mTouchWindow->consumeAnyMotionDown();
12157}
12158
12159TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
12160 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012161 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12162 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012163 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012164 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12165 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012166 mDispatcher->onWindowInfosChanged(
12167 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012168
12169 touch();
12170
12171 mTouchWindow->assertNoEvents();
12172}
12173
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012174TEST_F(InputDispatcherUntrustedTouchesTest,
12175 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
12176 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012177 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12178 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012179 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012180 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12181 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012182 mDispatcher->onWindowInfosChanged(
12183 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012184
12185 touch();
12186
12187 mTouchWindow->assertNoEvents();
12188}
12189
12190TEST_F(InputDispatcherUntrustedTouchesTest,
12191 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
12192 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012193 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12194 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012195 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012196 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12197 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012198 mDispatcher->onWindowInfosChanged(
12199 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012200
12201 touch();
12202
12203 mTouchWindow->consumeAnyMotionDown();
12204}
12205
12206TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
12207 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012208 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12209 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012210 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012211
12212 touch();
12213
12214 mTouchWindow->consumeAnyMotionDown();
12215}
12216
12217TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
12218 const sp<FakeWindowHandle>& w =
12219 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012220 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012221
12222 touch();
12223
12224 mTouchWindow->consumeAnyMotionDown();
12225}
12226
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012227TEST_F(InputDispatcherUntrustedTouchesTest,
12228 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
12229 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12230 const sp<FakeWindowHandle>& w =
12231 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012232 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012233
12234 touch();
12235
12236 mTouchWindow->assertNoEvents();
12237}
12238
12239TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
12240 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12241 const sp<FakeWindowHandle>& w =
12242 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012243 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012244
12245 touch();
12246
12247 mTouchWindow->consumeAnyMotionDown();
12248}
12249
12250TEST_F(InputDispatcherUntrustedTouchesTest,
12251 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
12252 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
12253 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012254 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12255 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012256 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012257
12258 touch();
12259
12260 mTouchWindow->consumeAnyMotionDown();
12261}
12262
12263TEST_F(InputDispatcherUntrustedTouchesTest,
12264 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
12265 const sp<FakeWindowHandle>& w1 =
12266 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12267 OPACITY_BELOW_THRESHOLD);
12268 const sp<FakeWindowHandle>& w2 =
12269 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12270 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012271 mDispatcher->onWindowInfosChanged(
12272 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012273
12274 touch();
12275
12276 mTouchWindow->assertNoEvents();
12277}
12278
12279/**
12280 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
12281 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
12282 * (which alone would result in allowing touches) does not affect the blocking behavior.
12283 */
12284TEST_F(InputDispatcherUntrustedTouchesTest,
12285 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
12286 const sp<FakeWindowHandle>& wB =
12287 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12288 OPACITY_BELOW_THRESHOLD);
12289 const sp<FakeWindowHandle>& wC =
12290 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12291 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012292 mDispatcher->onWindowInfosChanged(
12293 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012294
12295 touch();
12296
12297 mTouchWindow->assertNoEvents();
12298}
12299
12300/**
12301 * This test is testing that a window from a different UID but with same application token doesn't
12302 * block the touch. Apps can share the application token for close UI collaboration for example.
12303 */
12304TEST_F(InputDispatcherUntrustedTouchesTest,
12305 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
12306 const sp<FakeWindowHandle>& w =
12307 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
12308 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012309 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012310
12311 touch();
12312
12313 mTouchWindow->consumeAnyMotionDown();
12314}
12315
arthurhungb89ccb02020-12-30 16:19:01 +080012316class InputDispatcherDragTests : public InputDispatcherTest {
12317protected:
12318 std::shared_ptr<FakeApplicationHandle> mApp;
12319 sp<FakeWindowHandle> mWindow;
12320 sp<FakeWindowHandle> mSecondWindow;
12321 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012322 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012323 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
12324 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080012325
12326 void SetUp() override {
12327 InputDispatcherTest::SetUp();
12328 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012329 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12330 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080012331 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080012332
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012333 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12334 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080012335 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080012336
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012337 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
12338 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012339 mSpyWindow->setSpy(true);
12340 mSpyWindow->setTrustedOverlay(true);
12341 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
12342
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012343 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012344 mDispatcher->onWindowInfosChanged(
12345 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
12346 {},
12347 0,
12348 0});
arthurhungb89ccb02020-12-30 16:19:01 +080012349 }
12350
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012351 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
12352 switch (fromSource) {
12353 case AINPUT_SOURCE_TOUCHSCREEN:
12354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012355 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012356 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12358 break;
12359 case AINPUT_SOURCE_STYLUS:
12360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012361 injectMotionEvent(*mDispatcher,
12362 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12363 AINPUT_SOURCE_STYLUS)
12364 .buttonState(
12365 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
12366 .pointer(PointerBuilder(0, ToolType::STYLUS)
12367 .x(50)
12368 .y(50))
12369 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012370 break;
12371 case AINPUT_SOURCE_MOUSE:
12372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012373 injectMotionEvent(*mDispatcher,
12374 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12375 AINPUT_SOURCE_MOUSE)
12376 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
12377 .pointer(PointerBuilder(MOUSE_POINTER_ID,
12378 ToolType::MOUSE)
12379 .x(50)
12380 .y(50))
12381 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012382 break;
12383 default:
12384 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
12385 }
arthurhungb89ccb02020-12-30 16:19:01 +080012386
12387 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012388 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012389 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012390 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012391 }
12392
12393 // Start performing drag, we will create a drag window and transfer touch to it.
12394 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
12395 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012396 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000012397 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012398 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000012399 }
arthurhungb89ccb02020-12-30 16:19:01 +080012400
12401 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012402 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
12403 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012404 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012405 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
12406 *mWindow->getInfo(), *mSecondWindow->getInfo()},
12407 {},
12408 0,
12409 0});
arthurhungb89ccb02020-12-30 16:19:01 +080012410
12411 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000012412 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000012413 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
12414 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000012415 if (transferred) {
12416 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012417 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12418 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012419 }
12420 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080012421 }
12422};
12423
12424TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012425 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080012426
12427 // Move on window.
12428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012429 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012430 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012432 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12433 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012434 mWindow->consumeDragEvent(false, 50, 50);
12435 mSecondWindow->assertNoEvents();
12436
12437 // Move to another window.
12438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012439 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012440 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012442 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12443 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012444 mWindow->consumeDragEvent(true, 150, 50);
12445 mSecondWindow->consumeDragEvent(false, 50, 50);
12446
12447 // Move back to original window.
12448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012449 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012450 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012452 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12453 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012454 mWindow->consumeDragEvent(false, 50, 50);
12455 mSecondWindow->consumeDragEvent(true, -50, 50);
12456
12457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012458 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012459 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012460 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012461 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012462 mWindow->assertNoEvents();
12463 mSecondWindow->assertNoEvents();
12464}
12465
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012466TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012467 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012468
12469 // No cancel event after drag start
12470 mSpyWindow->assertNoEvents();
12471
12472 const MotionEvent secondFingerDownEvent =
12473 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12474 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012475 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12476 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012477 .build();
12478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012479 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012480 InputEventInjectionSync::WAIT_FOR_RESULT))
12481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12482
12483 // Receives cancel for first pointer after next pointer down
12484 mSpyWindow->consumeMotionCancel();
12485 mSpyWindow->consumeMotionDown();
12486
12487 mSpyWindow->assertNoEvents();
12488}
12489
arthurhungf452d0b2021-01-06 00:19:52 +080012490TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012491 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080012492
12493 // Move on window.
12494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012495 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012496 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012498 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12499 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012500 mWindow->consumeDragEvent(false, 50, 50);
12501 mSecondWindow->assertNoEvents();
12502
12503 // Move to another window.
12504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012505 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012506 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012507 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012508 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12509 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012510 mWindow->consumeDragEvent(true, 150, 50);
12511 mSecondWindow->consumeDragEvent(false, 50, 50);
12512
12513 // drop to another window.
12514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012515 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080012516 {150, 50}))
12517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012518 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012519 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080012520 mWindow->assertNoEvents();
12521 mSecondWindow->assertNoEvents();
12522}
12523
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012524TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
12525 startDrag();
12526
12527 // No cancel event after drag start
12528 mSpyWindow->assertNoEvents();
12529
12530 const MotionEvent secondFingerDownEvent =
12531 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12532 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12533 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12534 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12535 .build();
12536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12537 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12538 InputEventInjectionSync::WAIT_FOR_RESULT))
12539 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12540
12541 // Receives cancel for first pointer after next pointer down
12542 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080012543 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012544 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
12545
12546 mSpyWindow->assertNoEvents();
12547
12548 // Spy window calls pilfer pointers
12549 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
12550 mDragWindow->assertNoEvents();
12551
12552 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012553 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012554 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12555 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
12556 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12557 .build();
12558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012559 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012560 InputEventInjectionSync::WAIT_FOR_RESULT))
12561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12562
12563 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000012564 mDragWindow->consumeMotionEvent(
12565 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012566 mDragWindow->assertNoEvents();
12567}
12568
arthurhung6d4bed92021-03-17 11:59:33 +080012569TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012570 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080012571
12572 // Move on window and keep button pressed.
12573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012574 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012575 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12576 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012577 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012578 .build()))
12579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012580 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12581 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012582 mWindow->consumeDragEvent(false, 50, 50);
12583 mSecondWindow->assertNoEvents();
12584
12585 // Move to another window and release button, expect to drop item.
12586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012587 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012588 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12589 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012591 .build()))
12592 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012593 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12594 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012595 mWindow->assertNoEvents();
12596 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012597 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080012598
12599 // nothing to the window.
12600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012601 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012602 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
12603 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012604 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012605 .build()))
12606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012607 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012608 mWindow->assertNoEvents();
12609 mSecondWindow->assertNoEvents();
12610}
12611
Arthur Hung54745652022-04-20 07:17:41 +000012612TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012613 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080012614
12615 // Set second window invisible.
12616 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012617 mDispatcher->onWindowInfosChanged(
12618 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080012619
12620 // Move on window.
12621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012622 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012623 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012625 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12626 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012627 mWindow->consumeDragEvent(false, 50, 50);
12628 mSecondWindow->assertNoEvents();
12629
12630 // Move to another window.
12631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012632 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012633 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012635 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12636 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012637 mWindow->consumeDragEvent(true, 150, 50);
12638 mSecondWindow->assertNoEvents();
12639
12640 // drop to another window.
12641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012642 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080012643 {150, 50}))
12644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012645 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012646 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012647 mWindow->assertNoEvents();
12648 mSecondWindow->assertNoEvents();
12649}
12650
Arthur Hung54745652022-04-20 07:17:41 +000012651TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012652 // Ensure window could track pointerIds if it didn't support split touch.
12653 mWindow->setPreventSplitting(true);
12654
Arthur Hung54745652022-04-20 07:17:41 +000012655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012656 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12657 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012659 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012660
12661 const MotionEvent secondFingerDownEvent =
12662 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012663 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012664 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012665 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12666 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012667 .build();
12668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012669 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012670 InputEventInjectionSync::WAIT_FOR_RESULT))
12671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012672 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000012673
12674 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012675 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012676}
12677
12678TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12679 // First down on second window.
12680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012681 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12682 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12684
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012685 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012686
12687 // Second down on first window.
12688 const MotionEvent secondFingerDownEvent =
12689 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012690 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012691 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012692 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12693 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012694 .build();
12695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012696 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012697 InputEventInjectionSync::WAIT_FOR_RESULT))
12698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012699 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12700 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012701
12702 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012703 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012704
12705 // Move on window.
12706 const MotionEvent secondFingerMoveEvent =
12707 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12708 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012709 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12710 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012711 .build();
12712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012713 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012714 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012715 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12716 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012717 mWindow->consumeDragEvent(false, 50, 50);
12718 mSecondWindow->consumeMotionMove();
12719
12720 // Release the drag pointer should perform drop.
12721 const MotionEvent secondFingerUpEvent =
12722 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12723 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012724 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12725 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012726 .build();
12727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012728 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012729 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012730 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012731 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012732 mWindow->assertNoEvents();
12733 mSecondWindow->consumeMotionMove();
12734}
12735
Arthur Hung3915c1f2022-05-31 07:17:17 +000012736TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012737 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012738
12739 // Update window of second display.
12740 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012741 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012742 mDispatcher->onWindowInfosChanged(
12743 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12744 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12745 {},
12746 0,
12747 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012748
12749 // Let second display has a touch state.
12750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012751 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012752 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12753 AINPUT_SOURCE_TOUCHSCREEN)
12754 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012755 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012756 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012757 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012758 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012759 mDispatcher->onWindowInfosChanged(
12760 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12761 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12762 {},
12763 0,
12764 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012765
12766 // Move on window.
12767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012768 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012769 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012771 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12772 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012773 mWindow->consumeDragEvent(false, 50, 50);
12774 mSecondWindow->assertNoEvents();
12775
12776 // Move to another window.
12777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012778 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012779 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012781 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12782 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012783 mWindow->consumeDragEvent(true, 150, 50);
12784 mSecondWindow->consumeDragEvent(false, 50, 50);
12785
12786 // drop to another window.
12787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012788 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012789 {150, 50}))
12790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012791 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012792 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012793 mWindow->assertNoEvents();
12794 mSecondWindow->assertNoEvents();
12795}
12796
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012797TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12798 startDrag(true, AINPUT_SOURCE_MOUSE);
12799 // Move on window.
12800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012801 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012802 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12803 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012804 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012805 .x(50)
12806 .y(50))
12807 .build()))
12808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012809 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12810 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012811 mWindow->consumeDragEvent(false, 50, 50);
12812 mSecondWindow->assertNoEvents();
12813
12814 // Move to another window.
12815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012816 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012817 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12818 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012819 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012820 .x(150)
12821 .y(50))
12822 .build()))
12823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012824 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12825 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012826 mWindow->consumeDragEvent(true, 150, 50);
12827 mSecondWindow->consumeDragEvent(false, 50, 50);
12828
12829 // drop to another window.
12830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012831 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012832 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12833 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012834 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012835 .x(150)
12836 .y(50))
12837 .build()))
12838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012839 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012840 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012841 mWindow->assertNoEvents();
12842 mSecondWindow->assertNoEvents();
12843}
12844
Linnan Li5af92f92023-07-14 14:36:22 +080012845/**
12846 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12847 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12848 */
12849TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12850 // Down on second window
12851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12853 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12855
12856 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12857 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12858
12859 // Down on first window
12860 const MotionEvent secondFingerDownEvent =
12861 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012862 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012863 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12864 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12865 .build();
12866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12867 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12868 InputEventInjectionSync::WAIT_FOR_RESULT))
12869 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12870 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12871 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12872 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12873
12874 // Start drag on first window
12875 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12876
12877 // Trigger cancel
12878 mDispatcher->cancelCurrentTouch();
12879 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012880 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012881 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012882 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12883
12884 ASSERT_TRUE(mDispatcher->waitForIdle());
12885 // The D&D finished with nullptr
12886 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12887
12888 // Remove drag window
12889 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12890
Siarhei Vishniakou67b101b2024-10-12 00:42:44 +000012891 // Complete the first event stream, even though the injection will fail because there aren't any
12892 // valid targets to dispatch this event to. This is still needed to make the input stream
12893 // consistent
12894 ASSERT_EQ(InputEventInjectionResult::FAILED,
12895 injectMotionEvent(*mDispatcher,
12896 MotionEventBuilder(ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
12897 .displayId(ui::LogicalDisplayId::DEFAULT)
12898 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
12899 .x(150)
12900 .y(50))
12901 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
12902 .x(50)
12903 .y(50))
12904 .build(),
12905 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT));
12906
Linnan Li5af92f92023-07-14 14:36:22 +080012907 // Inject a simple gesture, ensure dispatcher not crashed
12908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012909 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12910 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12912 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12913
12914 const MotionEvent moveEvent =
12915 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012916 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012917 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12918 .build();
12919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12920 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12921 InputEventInjectionSync::WAIT_FOR_RESULT))
12922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12923 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12924
12925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012926 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012927 {50, 50}))
12928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12929 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12930}
12931
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012932TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12933 // Start hovering over the window.
12934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12935 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012936 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012937
12938 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12939 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12940
12941 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12942 << "Drag and drop should not work with a hovering pointer";
12943}
12944
Linnan Lia512a532024-10-08 16:19:16 +080012945/**
12946 * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if
12947 * we perform a click using Device B, the dispatcher should work well.
12948 */
12949TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) {
12950 const DeviceId deviceA = 1;
12951 const DeviceId deviceB = 2;
12952 // First down on second window with deviceA.
12953 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12954 .deviceId(deviceA)
12955 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12956 .build());
12957 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12958 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12959
12960 // Second down on first window with deviceA
12961 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12962 .deviceId(deviceA)
12963 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12964 .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50))
12965 .build());
12966 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12967 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12968 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12969 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12970
12971 // Perform drag and drop from first window.
12972 ASSERT_TRUE(startDrag(/*sendDown=*/false));
12973
12974 // Click first window with device B, we should ensure dispatcher work well.
12975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
12976 .deviceId(deviceB)
12977 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12978 .build());
12979 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
12980 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12981
12982 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
12983 .deviceId(deviceB)
12984 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12985 .build());
12986 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB),
12987 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12988
12989 // Move with device A.
12990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12991 .deviceId(deviceA)
12992 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12993 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12994 .build());
12995
12996 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12997 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12998 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12999 mWindow->consumeDragEvent(false, 51, 51);
13000 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
13001 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13002
13003 // Releasing the drag pointer should cause drop.
13004 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13005 .deviceId(deviceA)
13006 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
13007 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
13008 .build());
13009 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
13010 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13011 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
13012 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
13013 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
13014 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13015
13016 // Release all pointers.
13017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13018 .deviceId(deviceA)
13019 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
13020 .build());
13021 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
13022 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13023 mWindow->assertNoEvents();
13024}
13025
Vishnu Nair062a8672021-09-03 16:07:44 -070013026class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
13027
13028TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
13029 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013030 sp<FakeWindowHandle> window =
13031 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13032 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013033 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013034 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070013035 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013036 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013037 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013038 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070013039
13040 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013041 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013042 window->assertNoEvents();
13043
Prabir Pradhan678438e2023-04-13 19:32:51 +000013044 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013045 AINPUT_SOURCE_TOUCHSCREEN,
13046 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070013047 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013048 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080013049 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070013050 window->assertNoEvents();
13051
13052 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013053 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013054 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013055
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013056 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13057 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013058
Prabir Pradhan678438e2023-04-13 19:32:51 +000013059 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013060 AINPUT_SOURCE_TOUCHSCREEN,
13061 ui::LogicalDisplayId::DEFAULT));
13062 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013063 window->assertNoEvents();
13064}
13065
13066TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
13067 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
13068 std::make_shared<FakeApplicationHandle>();
13069 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013070 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013071 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013072 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013073 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013074 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070013075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013076 sp<FakeWindowHandle> window =
13077 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13078 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013079 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013080 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013081 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070013082 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013083 mDispatcher->onWindowInfosChanged(
13084 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013085 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013086 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070013087
13088 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013089 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013090 window->assertNoEvents();
13091
Prabir Pradhan678438e2023-04-13 19:32:51 +000013092 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013093 AINPUT_SOURCE_TOUCHSCREEN,
13094 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070013095 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013096 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013097 window->assertNoEvents();
13098
13099 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013100 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013101 mDispatcher->onWindowInfosChanged(
13102 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013103
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013104 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13105 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013106
Prabir Pradhan678438e2023-04-13 19:32:51 +000013107 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013108 AINPUT_SOURCE_TOUCHSCREEN,
13109 ui::LogicalDisplayId::DEFAULT));
13110 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
13111 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070013112 window->assertNoEvents();
13113}
13114
13115TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
13116 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
13117 std::make_shared<FakeApplicationHandle>();
13118 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013119 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013120 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013121 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013122 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013123 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070013124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013125 sp<FakeWindowHandle> window =
13126 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13127 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013128 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013129 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013130 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070013131 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013132 mDispatcher->onWindowInfosChanged(
13133 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013134 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013135 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070013136
13137 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013138 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013139 window->assertNoEvents();
13140
Prabir Pradhan678438e2023-04-13 19:32:51 +000013141 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013142 AINPUT_SOURCE_TOUCHSCREEN,
13143 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070013144 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013145 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013146 window->assertNoEvents();
13147
13148 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013149 mDispatcher->onWindowInfosChanged(
13150 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013151
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013152 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13153 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013154
Prabir Pradhan678438e2023-04-13 19:32:51 +000013155 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013156 AINPUT_SOURCE_TOUCHSCREEN,
13157 ui::LogicalDisplayId::DEFAULT));
13158 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013159 window->assertNoEvents();
13160}
13161
Antonio Kantekf16f2832021-09-28 04:39:20 +000013162class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
13163protected:
13164 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000013165 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000013166 sp<FakeWindowHandle> mWindow;
13167 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000013168 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000013169
13170 void SetUp() override {
13171 InputDispatcherTest::SetUp();
13172
13173 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000013174 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013175 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
13176 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013177 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013178 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013179 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
13180 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013181 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000013182 mThirdWindow =
13183 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
13184 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
13185 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013186
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013187 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013188 mDispatcher->onWindowInfosChanged(
13189 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
13190 {},
13191 0,
13192 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000013193 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013194 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013195
Antonio Kantek15beb512022-06-13 22:35:41 +000013196 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013197 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013198 WINDOW_UID, /*hasPermission=*/true,
13199 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070013200 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
13201 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000013202 mThirdWindow->assertNoEvents();
13203 }
13204
13205 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
13206 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000013207 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000013208 SECOND_DISPLAY_ID)) {
13209 mWindow->assertNoEvents();
13210 mSecondWindow->assertNoEvents();
13211 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070013212 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000013213 }
13214
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013215 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000013216 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070013217 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013218 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000013219 mWindow->consumeTouchModeEvent(inTouchMode);
13220 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000013221 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000013222 }
13223};
13224
Antonio Kantek26defcf2022-02-08 01:12:27 +000013225TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080013226 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000013227 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
13228 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000013229 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013230}
13231
Antonio Kantek26defcf2022-02-08 01:12:27 +000013232TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
13233 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013234 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013235 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013236 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013237 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000013238 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013239 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000013240 mWindow->assertNoEvents();
13241 mSecondWindow->assertNoEvents();
13242}
13243
13244TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
13245 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013246 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013247 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013248 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000013249 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000013250 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013251}
13252
Antonio Kantekf16f2832021-09-28 04:39:20 +000013253TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080013254 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000013255 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
13256 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013257 /*hasPermission=*/true,
13258 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000013259 mWindow->assertNoEvents();
13260 mSecondWindow->assertNoEvents();
13261}
13262
Antonio Kantek15beb512022-06-13 22:35:41 +000013263TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
13264 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
13265 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13266 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000013267 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000013268 mWindow->assertNoEvents();
13269 mSecondWindow->assertNoEvents();
13270 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
13271}
13272
Antonio Kantek48710e42022-03-24 14:19:30 -070013273TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
13274 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013276 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070013277 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013278 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070013279
13280 // Then remove focus.
13281 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013282 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070013283
13284 // Assert that caller can switch touch mode by owning one of the last interacted window.
13285 const WindowInfo& windowInfo = *mWindow->getInfo();
13286 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13287 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013288 /*hasPermission=*/false,
13289 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070013290}
13291
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013292class InputDispatcherSpyWindowTest : public InputDispatcherTest {
13293public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013294 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013295 std::shared_ptr<FakeApplicationHandle> application =
13296 std::make_shared<FakeApplicationHandle>();
13297 std::string name = "Fake Spy ";
13298 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013299 sp<FakeWindowHandle> spy =
13300 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
13301 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013302 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013303 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013304 return spy;
13305 }
13306
13307 sp<FakeWindowHandle> createForeground() {
13308 std::shared_ptr<FakeApplicationHandle> application =
13309 std::make_shared<FakeApplicationHandle>();
13310 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013311 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013312 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013313 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013314 return window;
13315 }
13316
13317private:
13318 int mSpyCount{0};
13319};
13320
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013321using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013322/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013323 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
13324 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013325TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070013326 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013327 ScopedSilentDeath _silentDeath;
13328
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013329 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013330 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013331 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013332 ".* not a trusted overlay");
13333}
13334
13335/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013336 * Input injection into a display with a spy window but no foreground windows should succeed.
13337 */
13338TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013339 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013340 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013341
13342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013343 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13344 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013345 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013346 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013347}
13348
13349/**
13350 * Verify the order in which different input windows receive events. The touched foreground window
13351 * (if there is one) should always receive the event first. When there are multiple spy windows, the
13352 * spy windows will receive the event according to their Z-order, where the top-most spy window will
13353 * receive events before ones belows it.
13354 *
13355 * Here, we set up a scenario with four windows in the following Z order from the top:
13356 * spy1, spy2, window, spy3.
13357 * We then inject an event and verify that the foreground "window" receives it first, followed by
13358 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
13359 * window.
13360 */
13361TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
13362 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013363 auto spy1 = createSpy();
13364 auto spy2 = createSpy();
13365 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013366 mDispatcher->onWindowInfosChanged(
13367 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013368 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
13369 const size_t numChannels = channels.size();
13370
Michael Wright8e9a8562022-02-09 13:44:29 +000013371 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013372 if (!epollFd.ok()) {
13373 FAIL() << "Failed to create epoll fd";
13374 }
13375
13376 for (size_t i = 0; i < numChannels; i++) {
13377 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
13378 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
13379 FAIL() << "Failed to add fd to epoll";
13380 }
13381 }
13382
13383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013384 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13385 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013386 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13387
13388 std::vector<size_t> eventOrder;
13389 std::vector<struct epoll_event> events(numChannels);
13390 for (;;) {
13391 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
13392 (100ms).count());
13393 if (nFds < 0) {
13394 FAIL() << "Failed to call epoll_wait";
13395 }
13396 if (nFds == 0) {
13397 break; // epoll_wait timed out
13398 }
13399 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070013400 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070013401 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013402 channels[i]->consumeMotionDown();
13403 }
13404 }
13405
13406 // Verify the order in which the events were received.
13407 EXPECT_EQ(3u, eventOrder.size());
13408 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
13409 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
13410 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
13411}
13412
13413/**
13414 * A spy window using the NOT_TOUCHABLE flag does not receive events.
13415 */
13416TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
13417 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013418 auto spy = createSpy();
13419 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013420 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013421
13422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013423 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13424 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013425 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013426 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013427 spy->assertNoEvents();
13428}
13429
13430/**
13431 * A spy window will only receive gestures that originate within its touchable region. Gestures that
13432 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
13433 * to the window.
13434 */
13435TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
13436 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013437 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013438 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013439 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013440
13441 // Inject an event outside the spy window's touchable region.
13442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013443 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13444 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13446 window->consumeMotionDown();
13447 spy->assertNoEvents();
13448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013449 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13450 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13452 window->consumeMotionUp();
13453 spy->assertNoEvents();
13454
13455 // Inject an event inside the spy window's touchable region.
13456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013457 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13458 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13460 window->consumeMotionDown();
13461 spy->consumeMotionDown();
13462}
13463
13464/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013465 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080013466 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013467 */
13468TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
13469 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013470 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013471 auto spy = createSpy();
13472 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013473 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013474 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013475 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013476
13477 // Inject an event outside the spy window's frame and touchable region.
13478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013479 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13480 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13482 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080013483 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013484}
13485
13486/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013487 * Even when a spy window spans over multiple foreground windows, the spy should receive all
13488 * pointers that are down within its bounds.
13489 */
13490TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
13491 auto windowLeft = createForeground();
13492 windowLeft->setFrame({0, 0, 100, 200});
13493 auto windowRight = createForeground();
13494 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013495 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013496 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013497 mDispatcher->onWindowInfosChanged(
13498 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013499
13500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013501 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13502 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13504 windowLeft->consumeMotionDown();
13505 spy->consumeMotionDown();
13506
13507 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013508 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013509 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013510 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13511 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013512 .build();
13513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013514 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013515 InputEventInjectionSync::WAIT_FOR_RESULT))
13516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13517 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000013518 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013519}
13520
13521/**
13522 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
13523 * the spy should receive the second pointer with ACTION_DOWN.
13524 */
13525TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
13526 auto window = createForeground();
13527 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013528 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013529 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013530 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013531
13532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013533 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13534 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13536 window->consumeMotionDown();
13537 spyRight->assertNoEvents();
13538
13539 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013540 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013541 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013542 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13543 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013544 .build();
13545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013546 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013547 InputEventInjectionSync::WAIT_FOR_RESULT))
13548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000013549 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013550 spyRight->consumeMotionDown();
13551}
13552
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013553/**
13554 * The spy window should not be able to affect whether or not touches are split. Only the foreground
13555 * windows should be allowed to control split touch.
13556 */
13557TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013558 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013559 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013560 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013561 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013562
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013563 auto window = createForeground();
13564 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013565
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013566 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013567
13568 // First finger down, no window touched.
13569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013570 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13571 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013572 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013573 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013574 window->assertNoEvents();
13575
13576 // Second finger down on window, the window should receive touch down.
13577 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013578 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013579 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013580 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013581 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13582 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013583 .build();
13584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013585 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013586 InputEventInjectionSync::WAIT_FOR_RESULT))
13587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13588
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013589 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000013590 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013591}
13592
13593/**
13594 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
13595 * do not receive key events.
13596 */
13597TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013598 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013599 spy->setFocusable(false);
13600
13601 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013602 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013603 setFocusedWindow(window);
13604 window->consumeFocusEvent(true);
13605
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013607 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013608 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013609
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013611 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013612 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013613
13614 spy->assertNoEvents();
13615}
13616
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013617using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
13618
13619/**
13620 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
13621 * are currently sent to any other windows - including other spy windows - will also be cancelled.
13622 */
13623TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
13624 auto window = createForeground();
13625 auto spy1 = createSpy();
13626 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013627 mDispatcher->onWindowInfosChanged(
13628 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013629
13630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013631 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13632 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13634 window->consumeMotionDown();
13635 spy1->consumeMotionDown();
13636 spy2->consumeMotionDown();
13637
13638 // Pilfer pointers from the second spy window.
13639 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
13640 spy2->assertNoEvents();
13641 spy1->consumeMotionCancel();
13642 window->consumeMotionCancel();
13643
13644 // The rest of the gesture should only be sent to the second spy window.
13645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013646 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013647 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13649 spy2->consumeMotionMove();
13650 spy1->assertNoEvents();
13651 window->assertNoEvents();
13652}
13653
13654/**
13655 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
13656 * in the middle of the gesture.
13657 */
13658TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13659 auto window = createForeground();
13660 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013661 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013662
13663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013664 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13665 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013667 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13668 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013669
13670 window->releaseChannel();
13671
13672 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13673
13674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013675 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13676 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013678 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013679}
13680
13681/**
13682 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13683 * the spy, but not to any other windows.
13684 */
13685TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13686 auto spy = createSpy();
13687 auto window = createForeground();
13688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013689 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013690
13691 // First finger down on the window and the spy.
13692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013693 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13694 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13696 spy->consumeMotionDown();
13697 window->consumeMotionDown();
13698
13699 // Spy window pilfers the pointers.
13700 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13701 window->consumeMotionCancel();
13702
13703 // Second finger down on the window and spy, but the window should not receive the pointer down.
13704 const MotionEvent secondFingerDownEvent =
13705 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013706 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013707 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013708 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13709 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013710 .build();
13711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013712 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013713 InputEventInjectionSync::WAIT_FOR_RESULT))
13714 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13715
Harry Cutts33476232023-01-30 19:57:29 +000013716 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013717
13718 // Third finger goes down outside all windows, so injection should fail.
13719 const MotionEvent thirdFingerDownEvent =
13720 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013721 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013722 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013723 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13724 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13725 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013726 .build();
13727 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013728 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013729 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080013730 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013731
13732 spy->assertNoEvents();
13733 window->assertNoEvents();
13734}
13735
13736/**
13737 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13738 */
13739TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13740 auto spy = createSpy();
13741 spy->setFrame(Rect(0, 0, 100, 100));
13742 auto window = createForeground();
13743 window->setFrame(Rect(0, 0, 200, 200));
13744
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013745 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013746
13747 // First finger down on the window only
13748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013749 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13750 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013751 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13752 window->consumeMotionDown();
13753
13754 // Second finger down on the spy and window
13755 const MotionEvent secondFingerDownEvent =
13756 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013757 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013758 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013759 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13760 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013761 .build();
13762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013763 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013764 InputEventInjectionSync::WAIT_FOR_RESULT))
13765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13766 spy->consumeMotionDown();
13767 window->consumeMotionPointerDown(1);
13768
13769 // Third finger down on the spy and window
13770 const MotionEvent thirdFingerDownEvent =
13771 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013772 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013773 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013774 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13775 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13776 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013777 .build();
13778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013779 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013780 InputEventInjectionSync::WAIT_FOR_RESULT))
13781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13782 spy->consumeMotionPointerDown(1);
13783 window->consumeMotionPointerDown(2);
13784
13785 // Spy window pilfers the pointers.
13786 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013787 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13788 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13789 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13790 WithPointerCount(3)));
13791 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13792 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13793 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13794 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013795
13796 spy->assertNoEvents();
13797 window->assertNoEvents();
13798}
13799
13800/**
13801 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13802 * other windows should be canceled. If this results in the cancellation of all pointers for some
13803 * window, then that window should receive ACTION_CANCEL.
13804 */
13805TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13806 auto spy = createSpy();
13807 spy->setFrame(Rect(0, 0, 100, 100));
13808 auto window = createForeground();
13809 window->setFrame(Rect(0, 0, 200, 200));
13810
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013811 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013812
13813 // First finger down on both spy and window
13814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013815 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13816 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13818 window->consumeMotionDown();
13819 spy->consumeMotionDown();
13820
13821 // Second finger down on the spy and window
13822 const MotionEvent secondFingerDownEvent =
13823 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013824 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013825 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013826 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13827 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013828 .build();
13829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013830 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013831 InputEventInjectionSync::WAIT_FOR_RESULT))
13832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13833 spy->consumeMotionPointerDown(1);
13834 window->consumeMotionPointerDown(1);
13835
13836 // Spy window pilfers the pointers.
13837 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13838 window->consumeMotionCancel();
13839
13840 spy->assertNoEvents();
13841 window->assertNoEvents();
13842}
13843
13844/**
13845 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13846 * be sent to other windows
13847 */
13848TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13849 auto spy = createSpy();
13850 spy->setFrame(Rect(0, 0, 100, 100));
13851 auto window = createForeground();
13852 window->setFrame(Rect(0, 0, 200, 200));
13853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013854 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013855
13856 // First finger down on both window and spy
13857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13859 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13861 window->consumeMotionDown();
13862 spy->consumeMotionDown();
13863
13864 // Spy window pilfers the pointers.
13865 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13866 window->consumeMotionCancel();
13867
13868 // Second finger down on the window only
13869 const MotionEvent secondFingerDownEvent =
13870 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013871 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013872 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013873 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13874 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013875 .build();
13876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013877 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013878 InputEventInjectionSync::WAIT_FOR_RESULT))
13879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13880 window->consumeMotionDown();
13881 window->assertNoEvents();
13882
13883 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13884 spy->consumeMotionMove();
13885 spy->assertNoEvents();
13886}
13887
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013888/**
13889 * A window on the left and a window on the right. Also, a spy window that's above all of the
13890 * windows, and spanning both left and right windows.
13891 * Send simultaneous motion streams from two different devices, one to the left window, and another
13892 * to the right window.
13893 * Pilfer from spy window.
13894 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13895 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013896TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13897 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013898 sp<FakeWindowHandle> spy = createSpy();
13899 spy->setFrame(Rect(0, 0, 200, 200));
13900 sp<FakeWindowHandle> leftWindow = createForeground();
13901 leftWindow->setFrame(Rect(0, 0, 100, 100));
13902
13903 sp<FakeWindowHandle> rightWindow = createForeground();
13904 rightWindow->setFrame(Rect(100, 0, 200, 100));
13905
13906 constexpr int32_t stylusDeviceId = 1;
13907 constexpr int32_t touchDeviceId = 2;
13908
13909 mDispatcher->onWindowInfosChanged(
13910 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13911
13912 // Stylus down on left window and spy
13913 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13914 .deviceId(stylusDeviceId)
13915 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13916 .build());
13917 leftWindow->consumeMotionEvent(
13918 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13919 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13920
13921 // Finger down on right window and spy - but spy already has stylus
13922 mDispatcher->notifyMotion(
13923 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13924 .deviceId(touchDeviceId)
13925 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13926 .build());
13927 rightWindow->consumeMotionEvent(
13928 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013929 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013930
13931 // Act: pilfer from spy. Spy is currently receiving touch events.
13932 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013933 leftWindow->consumeMotionEvent(
13934 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013935 rightWindow->consumeMotionEvent(
13936 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13937
13938 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13939 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13940 .deviceId(stylusDeviceId)
13941 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13942 .build());
13943 mDispatcher->notifyMotion(
13944 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13945 .deviceId(touchDeviceId)
13946 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13947 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013948 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013949
13950 spy->assertNoEvents();
13951 leftWindow->assertNoEvents();
13952 rightWindow->assertNoEvents();
13953}
13954
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013955/**
13956 * A window on the left and a window on the right. Also, a spy window that's above all of the
13957 * windows, and spanning both left and right windows.
13958 * Send simultaneous motion streams from two different devices, one to the left window, and another
13959 * to the right window.
13960 * Pilfer from spy window.
13961 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13962 * The spy should receive both the touch and the stylus events after pilfer.
13963 */
13964TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13965 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13966 sp<FakeWindowHandle> spy = createSpy();
13967 spy->setFrame(Rect(0, 0, 200, 200));
13968 sp<FakeWindowHandle> leftWindow = createForeground();
13969 leftWindow->setFrame(Rect(0, 0, 100, 100));
13970
13971 sp<FakeWindowHandle> rightWindow = createForeground();
13972 rightWindow->setFrame(Rect(100, 0, 200, 100));
13973
13974 constexpr int32_t stylusDeviceId = 1;
13975 constexpr int32_t touchDeviceId = 2;
13976
13977 mDispatcher->onWindowInfosChanged(
13978 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13979
13980 // Stylus down on left window and spy
13981 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13982 .deviceId(stylusDeviceId)
13983 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13984 .build());
13985 leftWindow->consumeMotionEvent(
13986 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13987 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13988
13989 // Finger down on right window and spy
13990 mDispatcher->notifyMotion(
13991 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13992 .deviceId(touchDeviceId)
13993 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13994 .build());
13995 rightWindow->consumeMotionEvent(
13996 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13997 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13998
13999 // Act: pilfer from spy. Spy is currently receiving touch events.
14000 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
14001 leftWindow->consumeMotionEvent(
14002 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
14003 rightWindow->consumeMotionEvent(
14004 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
14005
14006 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070014007 // Instead of sending the two MOVE events for each input device together, and then receiving
14008 // them both, process them one at at time. InputConsumer is always in the batching mode, which
14009 // means that the two MOVE events will be initially put into a batch. Once the events are
14010 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
14011 // on the implementation of InputConsumer), which would mean that the order of the received
14012 // events could be different depending on whether there are 1 or 2 events pending in the
14013 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
14014 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014015 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
14016 .deviceId(stylusDeviceId)
14017 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
14018 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070014019 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014020 mDispatcher->notifyMotion(
14021 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14022 .deviceId(touchDeviceId)
14023 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
14024 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070014025 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014026
14027 spy->assertNoEvents();
14028 leftWindow->assertNoEvents();
14029 rightWindow->assertNoEvents();
14030}
14031
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000014032TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
14033 auto window = createForeground();
14034 auto spy = createSpy();
14035 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
14036
14037 mDispatcher->notifyMotion(
14038 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
14039 .deviceId(1)
14040 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
14041 .build());
14042 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14043 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14044
14045 // Pilfer pointers from the spy window should fail.
14046 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
14047 spy->assertNoEvents();
14048 window->assertNoEvents();
14049}
14050
Prabir Pradhand65552b2021-10-07 11:23:50 -070014051class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
14052public:
14053 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
14054 std::shared_ptr<FakeApplicationHandle> overlayApplication =
14055 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014056 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
14057 "Stylus interceptor window",
14058 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014059 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014060 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080014061 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080014062 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014063 overlay->setTrustedOverlay(true);
14064
14065 std::shared_ptr<FakeApplicationHandle> application =
14066 std::make_shared<FakeApplicationHandle>();
14067 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070014068 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014069 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014070 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014071 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014072
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014073 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014074 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014075 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000014076 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014077 return {std::move(overlay), std::move(window)};
14078 }
14079
14080 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000014081 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070014082 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014083 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070014084 }
14085
14086 void sendStylusEvent(int32_t action) {
14087 NotifyMotionArgs motionArgs =
14088 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014089 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070014090 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000014091 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014092 }
14093};
14094
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080014095using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
14096
14097TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070014098 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080014099 ScopedSilentDeath _silentDeath;
14100
Prabir Pradhand65552b2021-10-07 11:23:50 -070014101 auto [overlay, window] = setupStylusOverlayScenario();
14102 overlay->setTrustedOverlay(false);
14103 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014104 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
14105 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070014106 ".* not a trusted overlay");
14107}
14108
14109TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
14110 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014111 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014112
14113 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14114 overlay->consumeMotionDown();
14115 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14116 overlay->consumeMotionUp();
14117
14118 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
14119 window->consumeMotionDown();
14120 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
14121 window->consumeMotionUp();
14122
14123 overlay->assertNoEvents();
14124 window->assertNoEvents();
14125}
14126
14127TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
14128 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080014129 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014130 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014131
14132 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14133 overlay->consumeMotionDown();
14134 window->consumeMotionDown();
14135 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14136 overlay->consumeMotionUp();
14137 window->consumeMotionUp();
14138
14139 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
14140 window->consumeMotionDown();
14141 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
14142 window->consumeMotionUp();
14143
14144 overlay->assertNoEvents();
14145 window->assertNoEvents();
14146}
14147
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000014148/**
14149 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
14150 * The scenario is as follows:
14151 * - The stylus interceptor overlay is configured as a spy window.
14152 * - The stylus interceptor spy receives the start of a new stylus gesture.
14153 * - It pilfers pointers and then configures itself to no longer be a spy.
14154 * - The stylus interceptor continues to receive the rest of the gesture.
14155 */
14156TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
14157 auto [overlay, window] = setupStylusOverlayScenario();
14158 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014159 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000014160
14161 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14162 overlay->consumeMotionDown();
14163 window->consumeMotionDown();
14164
14165 // The interceptor pilfers the pointers.
14166 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
14167 window->consumeMotionCancel();
14168
14169 // The interceptor configures itself so that it is no longer a spy.
14170 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014171 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000014172
14173 // It continues to receive the rest of the stylus gesture.
14174 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
14175 overlay->consumeMotionMove();
14176 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14177 overlay->consumeMotionUp();
14178
14179 window->assertNoEvents();
14180}
14181
Prabir Pradhan5735a322022-04-11 17:23:34 +000014182struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014183 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000014184 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000014185 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
14186 std::unique_ptr<InputDispatcher>& mDispatcher;
14187
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014188 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000014189 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
14190
14191 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014192 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014193 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000014194 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
14195 AMOTION_EVENT_INVALID_CURSOR_POSITION},
14196 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
14197 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
14198 }
14199
14200 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080014201 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014202 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000014203 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000014204 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000014205 mPolicyFlags);
14206 }
14207
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014208 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000014209 std::shared_ptr<FakeApplicationHandle> overlayApplication =
14210 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014211 sp<FakeWindowHandle> window =
14212 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
14213 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014214 window->setOwnerInfo(mPid, mUid);
14215 return window;
14216 }
14217};
14218
14219using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
14220
14221TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014222 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014223 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014224 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014225
14226 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14227 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14228 window->consumeMotionDown();
14229
14230 setFocusedWindow(window);
14231 window->consumeFocusEvent(true);
14232
14233 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14234 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014235 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014236}
14237
14238TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014239 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014240 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014241 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014242
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014243 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014244 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14245 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14246
14247 setFocusedWindow(window);
14248 window->consumeFocusEvent(true);
14249
14250 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14251 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
14252 window->assertNoEvents();
14253}
14254
14255TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014256 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014257 auto window = owner.createWindow("Owned window");
14258 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014259 spy->setSpy(true);
14260 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014261 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014262
14263 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14264 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14265 spy->consumeMotionDown();
14266 window->consumeMotionDown();
14267}
14268
14269TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014270 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014271 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014272
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014273 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014274 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014275 randosSpy->setSpy(true);
14276 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014277 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014278
14279 // The event is targeted at owner's window, so injection should succeed, but the spy should
14280 // not receive the event.
14281 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14282 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14283 randosSpy->assertNoEvents();
14284 window->consumeMotionDown();
14285}
14286
14287TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014288 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014289 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014290
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014291 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014292 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014293 randosSpy->setSpy(true);
14294 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014295 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014296
14297 // A user that has injection permission can inject into any window.
14298 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014299 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014300 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000014301 randosSpy->consumeMotionDown();
14302 window->consumeMotionDown();
14303
14304 setFocusedWindow(randosSpy);
14305 randosSpy->consumeFocusEvent(true);
14306
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014307 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014308 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014309 window->assertNoEvents();
14310}
14311
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014312TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014313 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014314 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014315
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014316 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014317 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014318 randosWindow->setFrame(Rect{-10, -10, -5, -5});
14319 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014320 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014321
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014322 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000014323 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14324 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14325 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014326 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000014327}
14328
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014329using InputDispatcherPointerInWindowTest = InputDispatcherTest;
14330
14331TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
14332 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14333
14334 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014335 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014336 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014337 sp<FakeWindowHandle> right =
14338 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14339 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014340 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014341 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14342 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014343 spy->setFrame(Rect(0, 0, 200, 100));
14344 spy->setTrustedOverlay(true);
14345 spy->setSpy(true);
14346
14347 mDispatcher->onWindowInfosChanged(
14348 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14349
14350 // Hover into the left window.
14351 mDispatcher->notifyMotion(
14352 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
14353 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
14354 .build());
14355
14356 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14357 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14358
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014359 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14360 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014361 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014362 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14363 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014364 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014365 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14366 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014367 /*pointerId=*/0));
14368
14369 // Hover move to the right window.
14370 mDispatcher->notifyMotion(
14371 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14372 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14373 .build());
14374
14375 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14376 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14377 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
14378
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014379 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14380 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014381 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014382 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14383 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014384 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014385 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14386 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014387 /*pointerId=*/0));
14388
14389 // Stop hovering.
14390 mDispatcher->notifyMotion(
14391 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
14392 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14393 .build());
14394
14395 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14396 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14397
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014398 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14399 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014400 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014401 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14402 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014403 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014404 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14405 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014406 /*pointerId=*/0));
14407}
14408
14409TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
14410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14411
14412 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014413 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014414 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014415 sp<FakeWindowHandle> right =
14416 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14417 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014418 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014419 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14420 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014421 spy->setFrame(Rect(0, 0, 200, 100));
14422 spy->setTrustedOverlay(true);
14423 spy->setSpy(true);
14424
14425 mDispatcher->onWindowInfosChanged(
14426 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14427
14428 // First pointer down on left window.
14429 mDispatcher->notifyMotion(
14430 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14431 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14432 .build());
14433
14434 left->consumeMotionDown();
14435 spy->consumeMotionDown();
14436
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014437 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14438 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014439 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014440 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14441 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014442 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014443 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14444 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014445 /*pointerId=*/0));
14446
14447 // Second pointer down on right window.
14448 mDispatcher->notifyMotion(
14449 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14450 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14451 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14452 .build());
14453
14454 left->consumeMotionMove();
14455 right->consumeMotionDown();
14456 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
14457
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014458 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14459 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014460 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014461 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14462 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014463 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014464 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14465 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014466 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014467 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14468 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014469 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014470 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14471 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014472 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014473 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14474 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014475 /*pointerId=*/1));
14476
14477 // Second pointer up.
14478 mDispatcher->notifyMotion(
14479 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
14480 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14481 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14482 .build());
14483
14484 left->consumeMotionMove();
14485 right->consumeMotionUp();
14486 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
14487
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014488 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14489 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014490 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014491 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14492 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014493 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014494 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14495 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014496 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014497 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14498 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014499 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014500 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14501 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014502 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014503 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14504 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014505 /*pointerId=*/1));
14506
14507 // First pointer up.
14508 mDispatcher->notifyMotion(
14509 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14510 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14511 .build());
14512
14513 left->consumeMotionUp();
14514 spy->consumeMotionUp();
14515
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014516 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14517 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014518 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014519 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14520 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014521 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014522 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14523 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014524 /*pointerId=*/0));
14525}
14526
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014527TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
14528 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14530
14531 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014532 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014533 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014534 sp<FakeWindowHandle> right =
14535 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14536 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014537 right->setFrame(Rect(100, 0, 200, 100));
14538
14539 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14540
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014541 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14542 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014543 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014544 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14545 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014546 /*pointerId=*/0));
14547
14548 // Hover move into the window.
14549 mDispatcher->notifyMotion(
14550 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14551 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14552 .rawXCursorPosition(50)
14553 .rawYCursorPosition(50)
14554 .deviceId(DEVICE_ID)
14555 .build());
14556
14557 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14558
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014559 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14560 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014561 /*pointerId=*/0));
14562
14563 // Move the mouse with another device. This cancels the hovering pointer from the first device.
14564 mDispatcher->notifyMotion(
14565 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14566 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14567 .rawXCursorPosition(51)
14568 .rawYCursorPosition(50)
14569 .deviceId(SECOND_DEVICE_ID)
14570 .build());
14571
14572 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14573 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14574
14575 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14576 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014577 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14578 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014579 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014580 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014581 SECOND_DEVICE_ID,
14582 /*pointerId=*/0));
14583
14584 // Move the mouse outside the window. Document the current behavior, where the window does not
14585 // receive HOVER_EXIT even though the mouse left the window.
14586 mDispatcher->notifyMotion(
14587 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14588 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14589 .rawXCursorPosition(150)
14590 .rawYCursorPosition(50)
14591 .deviceId(SECOND_DEVICE_ID)
14592 .build());
14593
14594 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14595 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014596 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14597 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014598 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014599 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014600 SECOND_DEVICE_ID,
14601 /*pointerId=*/0));
14602}
14603
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014604/**
14605 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
14606 * the same cursor, and therefore have a shared motion event stream.
14607 */
14608TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
14609 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
14610 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14611
14612 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014613 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014614 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014615 sp<FakeWindowHandle> right =
14616 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14617 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014618 right->setFrame(Rect(100, 0, 200, 100));
14619
14620 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14621
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014622 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14623 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014624 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014625 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14626 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014627 /*pointerId=*/0));
14628
14629 // Hover move into the window.
14630 mDispatcher->notifyMotion(
14631 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14632 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14633 .rawXCursorPosition(50)
14634 .rawYCursorPosition(50)
14635 .deviceId(DEVICE_ID)
14636 .build());
14637
14638 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14639
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014640 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14641 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014642 /*pointerId=*/0));
14643
14644 // Move the mouse with another device
14645 mDispatcher->notifyMotion(
14646 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14647 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14648 .rawXCursorPosition(51)
14649 .rawYCursorPosition(50)
14650 .deviceId(SECOND_DEVICE_ID)
14651 .build());
14652 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14653
14654 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14655 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014656 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14657 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014658 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014659 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014660 SECOND_DEVICE_ID,
14661 /*pointerId=*/0));
14662
14663 // Move the mouse outside the window. Document the current behavior, where the window does not
14664 // receive HOVER_EXIT even though the mouse left the window.
14665 mDispatcher->notifyMotion(
14666 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14667 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14668 .rawXCursorPosition(150)
14669 .rawYCursorPosition(50)
14670 .deviceId(SECOND_DEVICE_ID)
14671 .build());
14672
14673 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014674 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14675 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014676 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014677 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014678 SECOND_DEVICE_ID,
14679 /*pointerId=*/0));
14680}
14681
Arpit Singhb65e2bd2024-06-03 09:48:16 +000014682TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14683 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14684 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14685}
14686
Garfield Tane84e6f92019-08-29 17:28:41 -070014687} // namespace android::inputdispatcher