blob: c24d3029cefeee4fd014f0ac7393426d385c97ad [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhan81e89fe2024-03-20 21:17:09 +000019#include "FakeInputDispatcherPolicy.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhanc5340732024-03-20 22:53:52 +000021#include "FakeWindows.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000022#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080023
Cody Heiner166a5af2023-07-07 12:25:00 -070024#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000025#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070026#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080027#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070029#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070030#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000032#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000033#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080034#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080036#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100037#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070038#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070039#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080041#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080044#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070045#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080046#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080047#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Garfield Tan1c7bc862020-01-28 13:24:04 -080049using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050050using android::gui::FocusRequest;
51using android::gui::TouchOcclusionMode;
52using android::gui::WindowInfo;
53using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080054using android::os::InputEventInjectionResult;
55using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080056
Garfield Tane84e6f92019-08-29 17:28:41 -070057namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080060using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000061using testing::Not;
Siarhei Vishniakou85eb5802024-04-01 11:40:59 -070062using testing::Pointee;
63using testing::UnorderedElementsAre;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070064
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070065namespace {
66
Michael Wrightd02c5b62014-02-10 15:10:22 -080067// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000068static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080069
70// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000071static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080072static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080073
Jeff Brownf086ddb2014-02-11 14:28:48 -080074// An arbitrary display id.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070075constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Linnan Li13bf76a2024-05-05 19:18:02 +080076constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
Jeff Brownf086ddb2014-02-11 14:28:48 -080077
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000078// Ensure common actions are interchangeable between keys and motions for convenience.
79static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
80static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
82static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
83static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
84static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070085static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080086static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070087static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080088static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080089static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080090/**
91 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
92 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
93 * index 0) is the new pointer going down. The same pointer could have been placed at a different
94 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
95 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
96 * pointer id=0 leaves but the pointer id=1 remains.
97 */
98static constexpr int32_t POINTER_0_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100static constexpr int32_t POINTER_1_DOWN =
101 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +0000102static constexpr int32_t POINTER_2_DOWN =
103 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000104static constexpr int32_t POINTER_3_DOWN =
105 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000106static constexpr int32_t POINTER_0_UP =
107 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800108static constexpr int32_t POINTER_1_UP =
109 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000110static constexpr int32_t POINTER_2_UP =
111 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800112
Antonio Kantek15beb512022-06-13 22:35:41 +0000113// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000115static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000116
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000118static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000119
Linnan Li72352222024-04-12 18:55:57 +0800120static constexpr int EXPECTED_WALLPAPER_FLAGS =
Arthur Hungc539dbb2022-12-08 07:45:36 +0000121 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800123using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124
Gang Wang342c9272020-01-13 13:15:04 -0500125/**
126 * Return a DOWN key event with KEYCODE_A.
127 */
128static KeyEvent getTestKeyEvent() {
129 KeyEvent event;
130
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700131 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
132 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
133 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500134 return event;
135}
136
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700137/**
138 * Provide a local override for a flag value. The value is restored when the object of this class
139 * goes out of scope.
140 * This class is not intended to be used directly, because its usage is cumbersome.
141 * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
142 */
143class ScopedFlagOverride {
144public:
145 ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
146 : mInitialValue(read()), mWriteValue(write) {
147 mWriteValue(value);
148 }
149 ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
150
151private:
152 const bool mInitialValue;
153 std::function<void(bool)> mWriteValue;
154};
155
156typedef bool (*readFlagValueFunction)();
157typedef void (*writeFlagValueFunction)(bool);
158
159/**
160 * Use this macro to locally override a flag value.
161 * Example usage:
162 * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
163 * Note: this works by creating a local variable in your current scope. Don't call this twice for
164 * the same flag, because the variable names will clash!
165 */
166#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
167 readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
168 writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
169 ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
170
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172
Michael Wrightd02c5b62014-02-10 15:10:22 -0800173// --- InputDispatcherTest ---
174
175class InputDispatcherTest : public testing::Test {
176protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000177 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700178 std::unique_ptr<InputDispatcher> mDispatcher;
Prabir Pradhanc5340732024-03-20 22:53:52 +0000179 std::shared_ptr<VerifyingTrace> mVerifyingTrace;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 void SetUp() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000182 mVerifyingTrace = std::make_shared<VerifyingTrace>();
183 FakeWindowHandle::sOnEventReceivedCallback = [this](const auto& _1, const auto& _2) {
184 handleEventReceivedByWindow(_1, _2);
185 };
186
Prabir Pradhana41d2442023-04-20 21:30:40 +0000187 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000188 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
189 std::make_unique<FakeInputTracingBackend>(
Prabir Pradhanc5340732024-03-20 22:53:52 +0000190 mVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700191
Harry Cutts101ee9b2023-07-06 18:04:14 +0000192 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000193 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700194 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195 }
196
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000197 void TearDown() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000198 ASSERT_NO_FATAL_FAILURE(mVerifyingTrace->verifyExpectedEventsTraced());
199 FakeWindowHandle::sOnEventReceivedCallback = nullptr;
200
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700201 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000202 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700203 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205
Prabir Pradhanc5340732024-03-20 22:53:52 +0000206 void handleEventReceivedByWindow(const std::unique_ptr<InputEvent>& event,
207 const gui::WindowInfo& info) {
208 if (!event) {
209 return;
210 }
211
212 switch (event->getType()) {
213 case InputEventType::KEY: {
214 mVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), info.id);
215 break;
216 }
217 case InputEventType::MOTION: {
218 mVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
219 info.id);
220 break;
221 }
222 default:
223 break;
224 }
225 }
226
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700227 /**
228 * Used for debugging when writing the test
229 */
230 void dumpDispatcherState() {
231 std::string dump;
232 mDispatcher->dump(dump);
233 std::stringstream ss(dump);
234 std::string to;
235
236 while (std::getline(ss, to, '\n')) {
237 ALOGE("%s", to.c_str());
238 }
239 }
Vishnu Nair958da932020-08-21 17:12:37 -0700240
Chavi Weingarten847e8512023-03-29 00:26:09 +0000241 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700242 FocusRequest request;
243 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000244 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700245 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Linnan Li13bf76a2024-05-05 19:18:02 +0800246 request.displayId = window->getInfo()->displayId.val();
Vishnu Nair958da932020-08-21 17:12:37 -0700247 mDispatcher->setFocusedWindow(request);
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249};
250
Michael Wrightd02c5b62014-02-10 15:10:22 -0800251TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
252 KeyEvent event;
253
254 // Rejects undefined key actions.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700255 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
256 ui::LogicalDisplayId::INVALID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000257 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600258 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800259 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000260 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000261 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 << "Should reject key events with undefined action.";
263
264 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700265 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
266 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0,
267 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800268 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000269 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000270 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 << "Should reject key events with ACTION_MULTIPLE.";
272}
273
274TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
275 MotionEvent event;
276 PointerProperties pointerProperties[MAX_POINTERS + 1];
277 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800278 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279 pointerProperties[i].clear();
280 pointerProperties[i].id = i;
281 pointerCoords[i].clear();
282 }
283
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800284 // Some constants commonly used below
285 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
286 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
287 constexpr int32_t metaState = AMETA_NONE;
288 constexpr MotionClassification classification = MotionClassification::NONE;
289
chaviw9eaa22c2020-07-01 16:21:27 -0700290 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800292 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000293 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700294 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700295 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
296 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000297 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000299 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000300 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 << "Should reject motion events with undefined action.";
302
303 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800304 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800305 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
306 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
307 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
308 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000309 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800310 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000311 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000312 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 << "Should reject motion events with pointer down index too large.";
314
Garfield Tanfbe732e2020-01-24 11:26:14 -0800315 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700316 AMOTION_EVENT_ACTION_POINTER_DOWN |
317 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700318 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
319 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700320 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000321 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800322 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000323 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000324 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800325 << "Should reject motion events with pointer down index too small.";
326
327 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800328 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800329 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
330 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
331 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
332 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000333 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800334 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000335 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000336 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 << "Should reject motion events with pointer up index too large.";
338
Garfield Tanfbe732e2020-01-24 11:26:14 -0800339 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700340 AMOTION_EVENT_ACTION_POINTER_UP |
341 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700342 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
343 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700344 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000345 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000347 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000348 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 << "Should reject motion events with pointer up index too small.";
350
351 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800352 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
353 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700354 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700355 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
356 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000357 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800358 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000359 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000360 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361 << "Should reject motion events with 0 pointers.";
362
Garfield Tanfbe732e2020-01-24 11:26:14 -0800363 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
364 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700365 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700366 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
367 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000368 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800369 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000370 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000371 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800372 << "Should reject motion events with more than MAX_POINTERS pointers.";
373
374 // Rejects motion events with invalid pointer ids.
375 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800376 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
377 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700378 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700379 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
380 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000381 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800382 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000383 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000384 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385 << "Should reject motion events with pointer ids less than 0.";
386
387 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800388 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
389 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700390 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700391 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
392 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000393 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800394 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000395 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000396 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800397 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
398
399 // Rejects motion events with duplicate pointer ids.
400 pointerProperties[0].id = 1;
401 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800402 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
403 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700404 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700405 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
406 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000407 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000409 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000410 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411 << "Should reject motion events with duplicate pointer ids.";
412}
413
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800414/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
415
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800416TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000417 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
418 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000419 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000420 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800421
422 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
423 args.policyFlags |= POLICY_FLAG_TRUSTED;
424 mFakePolicy->assertNotifySwitchWasCalled(args);
425}
426
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700427namespace {
428
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700429static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700430
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000431class FakeMonitorReceiver {
432public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800433 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
434 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700435 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000436
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700437 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000438
Linnan Li13bf76a2024-05-05 19:18:02 +0800439 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700440 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
441 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000442 }
443
444 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800445 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
446 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000447 }
448
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700449 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000450
Linnan Li13bf76a2024-05-05 19:18:02 +0800451 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700452 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
453 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000454 }
455
Linnan Li13bf76a2024-05-05 19:18:02 +0800456 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700457 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
458 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000459 }
460
Linnan Li13bf76a2024-05-05 19:18:02 +0800461 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700462 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
463 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000464 }
465
Linnan Li13bf76a2024-05-05 19:18:02 +0800466 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700467 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000468 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
469 WithDisplayId(expectedDisplayId),
470 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
471 }
472
473 void consumeMotionPointerDown(int32_t pointerIdx) {
474 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
475 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700476 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700477 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000478 }
479
480 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700481 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000482 }
483
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800484 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000485
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800486 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000487
488private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700489 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000490};
491
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800492static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700493 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700494 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800495 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800496 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000497 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000498 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800499 KeyEvent event;
500 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
501
502 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800503 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000504 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
505 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800506
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800507 if (!allowKeyRepeat) {
508 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
509 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800510 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700511 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800512}
513
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700514static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
515 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700516 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
517 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
518 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700519 if (result != InputEventInjectionResult::TIMED_OUT) {
520 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
521 }
522}
523
Linnan Li13bf76a2024-05-05 19:18:02 +0800524static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700525 InputDispatcher& dispatcher,
526 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000527 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700528}
529
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800530// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
531// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
532// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800533static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700534 InputDispatcher& dispatcher,
535 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000536 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800537 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000538 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800539}
540
Linnan Li13bf76a2024-05-05 19:18:02 +0800541static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700542 InputDispatcher& dispatcher,
543 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000544 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700545}
546
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800547static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700548 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700549 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000550 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000551 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700552 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
553 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700554}
555
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800556static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800557 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700558 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700559 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700560 AMOTION_EVENT_INVALID_CURSOR_POSITION},
561 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800562 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000563 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000564 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700565 MotionEventBuilder motionBuilder =
566 MotionEventBuilder(action, source)
567 .displayId(displayId)
568 .eventTime(eventTime)
569 .rawXCursorPosition(cursorPosition.x)
570 .rawYCursorPosition(cursorPosition.y)
571 .pointer(
572 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
573 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
574 motionBuilder.downTime(eventTime);
575 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800576
577 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700578 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
579 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800580}
581
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700582static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800583 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700584 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700585 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700586}
587
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700588static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800589 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800590 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700591 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000592}
593
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700594static NotifyKeyArgs generateKeyArgs(
595 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800596 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
597 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000598 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
599 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
600 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800601
602 return args;
603}
604
Prabir Pradhan678438e2023-04-13 19:32:51 +0000605[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800606 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000607 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800608 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700609 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
610 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
611 }
612
chaviwd1c23182019-12-20 18:44:56 -0800613 PointerProperties pointerProperties[pointerCount];
614 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800615
chaviwd1c23182019-12-20 18:44:56 -0800616 for (size_t i = 0; i < pointerCount; i++) {
617 pointerProperties[i].clear();
618 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700619 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800620
chaviwd1c23182019-12-20 18:44:56 -0800621 pointerCoords[i].clear();
622 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
623 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
624 }
Jackal Guof9696682018-10-05 12:23:23 +0800625
626 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
627 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000628 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
629 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
630 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800631 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000632 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700633 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000634 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800635
636 return args;
637}
638
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800639static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
640 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
641}
642
Linnan Li13bf76a2024-05-05 19:18:02 +0800643static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
644 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800645 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
646}
647
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000648static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
649 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000650 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
651 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800652}
653
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700654} // namespace
655
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800656/**
657 * When a window unexpectedly disposes of its input channel, policy should be notified about the
658 * broken channel.
659 */
660TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700662 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
663 "Window that breaks its input channel",
664 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800665
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700666 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800667
668 // Window closes its channel, but the window remains.
669 window->destroyReceiver();
670 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
671}
672
Arthur Hungb92218b2018-08-14 12:00:21 +0800673TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700675 sp<FakeWindowHandle> window =
676 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
677 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800678
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700679 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700681 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
682 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800684
685 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700686 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800687}
688
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800689using InputDispatcherDeathTest = InputDispatcherTest;
690
691/**
692 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
693 * should crash.
694 */
695TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
696 testing::GTEST_FLAG(death_test_style) = "threadsafe";
697 ScopedSilentDeath _silentDeath;
698
699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700700 sp<FakeWindowHandle> window =
701 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
702 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800703 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
704 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
705 "Incorrect WindowInfosUpdate provided");
706}
707
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700708TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700710 sp<FakeWindowHandle> window =
711 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
712 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700715 // Inject a MotionEvent to an unknown display.
716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
718 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
720
721 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700722 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700723}
724
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700725/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700726 * Calling onWindowInfosChanged once should not cause any issues.
727 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700728 * called twice.
729 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800730TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700732 sp<FakeWindowHandle> window =
733 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
734 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700735 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700736
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
740 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700742
743 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700744 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700745}
746
747/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700748 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700749 */
750TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700752 sp<FakeWindowHandle> window =
753 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
754 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700755 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
758 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
761 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700763
764 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700765 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700766}
767
Arthur Hungb92218b2018-08-14 12:00:21 +0800768// The foreground window should receive the first touch down event.
769TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700771 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
772 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000773 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700774 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
775 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800776
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700777 mDispatcher->onWindowInfosChanged(
778 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
781 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800783
784 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700785 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800786 windowSecond->assertNoEvents();
787}
788
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000789/**
790 * Two windows: A top window, and a wallpaper behind the window.
791 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
792 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800793 * 1. foregroundWindow <-- dup touch to wallpaper
794 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000795 */
796TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
798 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700799 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
800 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800801 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000802 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700803 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
804 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800805 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000806
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700807 mDispatcher->onWindowInfosChanged(
808 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800810 injectMotionEvent(*mDispatcher,
811 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
812 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
813 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
815
816 // Both foreground window and its wallpaper should receive the touch down
817 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700818 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000819
820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800821 injectMotionEvent(*mDispatcher,
822 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
823 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
824 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
826
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800827 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700828 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000829
830 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700831 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000832 foregroundWindow->consumeMotionCancel();
833 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700834 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000835}
836
837/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800838 * Two fingers down on the window, and lift off the first finger.
839 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
840 * contains a single pointer.
841 */
842TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700844 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
845 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800848 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
850 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
851 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800852 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000853 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
854 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
855 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
856 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800857 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000858 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
859 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
860 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
861 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800862 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
863 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
864 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
865
866 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700867 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800868 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
869 window->consumeMotionEvent(
870 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
871}
872
873/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800874 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
875 * with the following differences:
876 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
877 * clean up the connection.
878 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
879 * Ensure that there's no crash in the dispatcher.
880 */
881TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
883 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700884 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
885 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800886 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800887 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700888 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
889 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800890 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800891
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700892 mDispatcher->onWindowInfosChanged(
893 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700895 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
896 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
898
899 // Both foreground window and its wallpaper should receive the touch down
900 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700901 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800902
903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700904 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700905 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
907
908 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700909 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800910
911 // Wallpaper closes its channel, but the window remains.
912 wallpaperWindow->destroyReceiver();
913 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
914
915 // Now the foreground window goes away, but the wallpaper stays, even though its channel
916 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700917 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800918 foregroundWindow->consumeMotionCancel();
919}
920
Linnan Li72352222024-04-12 18:55:57 +0800921/**
922 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
923 * down event to the left window. Device B sends a down event to the right window. Next, the right
924 * window disappears. Both the right window and its wallpaper window should receive cancel event.
925 * The left window and its wallpaper window should not receive any events.
926 */
927TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
929 sp<FakeWindowHandle> leftForegroundWindow =
930 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700931 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800932 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
933 leftForegroundWindow->setDupTouchToWallpaper(true);
934 sp<FakeWindowHandle> leftWallpaperWindow =
935 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700936 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800937 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
938 leftWallpaperWindow->setIsWallpaper(true);
939
940 sp<FakeWindowHandle> rightForegroundWindow =
941 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700942 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800943 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
944 rightForegroundWindow->setDupTouchToWallpaper(true);
945 sp<FakeWindowHandle> rightWallpaperWindow =
946 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700947 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800948 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
949 rightWallpaperWindow->setIsWallpaper(true);
950
951 mDispatcher->onWindowInfosChanged(
952 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
953 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
954 {},
955 0,
956 0});
957
958 const DeviceId deviceA = 9;
959 const DeviceId deviceB = 3;
960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
961 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
962 .deviceId(deviceA)
963 .build());
964 leftForegroundWindow->consumeMotionEvent(
965 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
966 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
967 WithDeviceId(deviceA),
968 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
969
970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
971 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
972 .deviceId(deviceB)
973 .build());
974 rightForegroundWindow->consumeMotionEvent(
975 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
976 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
977 WithDeviceId(deviceB),
978 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
979
980 // Now right foreground window disappears, but right wallpaper window remains.
981 mDispatcher->onWindowInfosChanged(
982 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
983 *rightWallpaperWindow->getInfo()},
984 {},
985 0,
986 0});
987
988 // Left foreground window and left wallpaper window still exist, and should not receive any
989 // events.
990 leftForegroundWindow->assertNoEvents();
991 leftWallpaperWindow->assertNoEvents();
992 // Since right foreground window disappeared, right wallpaper window and right foreground window
993 // should receive cancel events.
994 rightForegroundWindow->consumeMotionEvent(
995 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
996 rightWallpaperWindow->consumeMotionEvent(
997 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
998 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
999}
1000
1001/**
1002 * Three windows arranged horizontally and without any overlap. Every window has a
1003 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1004 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1005 * Next, device B sends move event to the right window. Touch for device B should slip from the
1006 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1007 * The middle window and its wallpaper window should receive a cancel event. The left window should
1008 * not receive any events. If device B continues to report events, the right window and its
1009 * wallpaper window should receive remaining events.
1010 */
1011TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1013 sp<FakeWindowHandle> leftForegroundWindow =
1014 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001015 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001016 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1017 leftForegroundWindow->setDupTouchToWallpaper(true);
1018 sp<FakeWindowHandle> leftWallpaperWindow =
1019 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001020 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001021 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1022 leftWallpaperWindow->setIsWallpaper(true);
1023
1024 sp<FakeWindowHandle> middleForegroundWindow =
1025 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001026 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001027 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1028 middleForegroundWindow->setDupTouchToWallpaper(true);
1029 middleForegroundWindow->setSlippery(true);
1030 sp<FakeWindowHandle> middleWallpaperWindow =
1031 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001032 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001033 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1034 middleWallpaperWindow->setIsWallpaper(true);
1035
1036 sp<FakeWindowHandle> rightForegroundWindow =
1037 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001038 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001039 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1040 rightForegroundWindow->setDupTouchToWallpaper(true);
1041 sp<FakeWindowHandle> rightWallpaperWindow =
1042 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001043 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001044 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1045 rightWallpaperWindow->setIsWallpaper(true);
1046
1047 mDispatcher->onWindowInfosChanged(
1048 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1049 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1050 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1051 {},
1052 0,
1053 0});
1054
1055 const DeviceId deviceA = 9;
1056 const DeviceId deviceB = 3;
1057 // Device A sends a DOWN event to the left window
1058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1059 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1060 .deviceId(deviceA)
1061 .build());
1062 leftForegroundWindow->consumeMotionEvent(
1063 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1064 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1065 WithDeviceId(deviceA),
1066 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1067 // Device B sends a DOWN event to the middle window
1068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1069 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1070 .deviceId(deviceB)
1071 .build());
1072 middleForegroundWindow->consumeMotionEvent(
1073 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1074 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1075 WithDeviceId(deviceB),
1076 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1077 // Move the events of device B to the top of the right window.
1078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1079 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1080 .deviceId(deviceB)
1081 .build());
1082 middleForegroundWindow->consumeMotionEvent(
1083 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1084 middleWallpaperWindow->consumeMotionEvent(
1085 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1086 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1087 rightForegroundWindow->consumeMotionEvent(
1088 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1089 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1090 WithDeviceId(deviceB),
1091 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1092 // Make sure the window on the right can receive the remaining events.
1093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1094 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1095 .deviceId(deviceB)
1096 .build());
1097 leftForegroundWindow->assertNoEvents();
1098 leftWallpaperWindow->assertNoEvents();
1099 middleForegroundWindow->assertNoEvents();
1100 middleWallpaperWindow->assertNoEvents();
1101 rightForegroundWindow->consumeMotionEvent(
1102 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1103 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1104 WithDeviceId(deviceB),
1105 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1106}
1107
1108/**
1109 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1110 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1111 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1112 * event to the middle window and then touch is transferred from the middle window to the right
1113 * window. The right window and its wallpaper window should receive a down event. The middle window
1114 * and its wallpaper window should receive a cancel event. The left window should not receive any
1115 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1116 */
1117TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1119 sp<FakeWindowHandle> leftForegroundWindow =
1120 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001121 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001122 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1123 leftForegroundWindow->setDupTouchToWallpaper(true);
1124 sp<FakeWindowHandle> leftWallpaperWindow =
1125 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001126 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001127 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1128 leftWallpaperWindow->setIsWallpaper(true);
1129
1130 sp<FakeWindowHandle> middleForegroundWindow =
1131 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001132 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001133 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1134 middleForegroundWindow->setDupTouchToWallpaper(true);
1135 sp<FakeWindowHandle> middleWallpaperWindow =
1136 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001137 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001138 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1139 middleWallpaperWindow->setIsWallpaper(true);
1140
1141 sp<FakeWindowHandle> rightForegroundWindow =
1142 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001143 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001144 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1145 rightForegroundWindow->setDupTouchToWallpaper(true);
1146 sp<FakeWindowHandle> rightWallpaperWindow =
1147 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001148 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001149 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1150 rightWallpaperWindow->setIsWallpaper(true);
1151
1152 mDispatcher->onWindowInfosChanged(
1153 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1154 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1155 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1156 {},
1157 0,
1158 0});
1159
1160 const DeviceId deviceA = 9;
1161 const DeviceId deviceB = 3;
1162 // Device A touch down on the left window
1163 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1164 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1165 .deviceId(deviceA)
1166 .build());
1167 leftForegroundWindow->consumeMotionEvent(
1168 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1169 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1170 WithDeviceId(deviceA),
1171 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1172 // Device B touch down on the middle window
1173 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1174 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1175 .deviceId(deviceB)
1176 .build());
1177 middleForegroundWindow->consumeMotionEvent(
1178 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1179 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1180 WithDeviceId(deviceB),
1181 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1182
1183 // Transfer touch from the middle window to the right window.
1184 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1185 rightForegroundWindow->getToken()));
1186
1187 middleForegroundWindow->consumeMotionEvent(
1188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1189 middleWallpaperWindow->consumeMotionEvent(
1190 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1191 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1192 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1193 WithDeviceId(deviceB),
1194 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1195 rightWallpaperWindow->consumeMotionEvent(
1196 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1197 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1198
1199 // Make sure the right window can receive the remaining events.
1200 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1201 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1202 .deviceId(deviceB)
1203 .build());
1204 leftForegroundWindow->assertNoEvents();
1205 leftWallpaperWindow->assertNoEvents();
1206 middleForegroundWindow->assertNoEvents();
1207 middleWallpaperWindow->assertNoEvents();
1208 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1209 WithDeviceId(deviceB),
1210 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1211 rightWallpaperWindow->consumeMotionEvent(
1212 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1213 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1214}
1215
Arthur Hungc539dbb2022-12-08 07:45:36 +00001216class ShouldSplitTouchFixture : public InputDispatcherTest,
1217 public ::testing::WithParamInterface<bool> {};
1218INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1219 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001220/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001221 * A single window that receives touch (on top), and a wallpaper window underneath it.
1222 * The top window gets a multitouch gesture.
1223 * Ensure that wallpaper gets the same gesture.
1224 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001225TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001227 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001228 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1229 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001230 foregroundWindow->setDupTouchToWallpaper(true);
1231 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001232
1233 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001234 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1235 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001236 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001237
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001238 mDispatcher->onWindowInfosChanged(
1239 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001240
1241 // Touch down on top window
1242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1244 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1246
1247 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001248 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001249 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001250
1251 // Second finger down on the top window
1252 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001253 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001254 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001255 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1256 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001257 .build();
1258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001259 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001260 InputEventInjectionSync::WAIT_FOR_RESULT))
1261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001262 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001263 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001264 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001265
1266 const MotionEvent secondFingerUpEvent =
1267 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001268 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001269 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001270 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1271 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001272 .build();
1273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001274 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001275 InputEventInjectionSync::WAIT_FOR_RESULT))
1276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001277 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1278 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1279 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1280 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1281 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001282
1283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001284 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001285 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1286 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001287 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001288 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001289 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001290 .x(100)
1291 .y(100))
1292 .build(),
1293 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001295 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1296 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001297}
1298
1299/**
1300 * Two windows: a window on the left and window on the right.
1301 * A third window, wallpaper, is behind both windows, and spans both top windows.
1302 * The first touch down goes to the left window. A second pointer touches down on the right window.
1303 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1304 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1305 * ACTION_POINTER_DOWN(1).
1306 */
1307TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001309 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1310 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001311 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001312 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001313
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001314 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1315 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001316 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001317 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001318
1319 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001320 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1321 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001322 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001323 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001324
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001325 mDispatcher->onWindowInfosChanged(
1326 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1327 {},
1328 0,
1329 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001330
1331 // Touch down on left window
1332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001333 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1334 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001335 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1336
1337 // Both foreground window and its wallpaper should receive the touch down
1338 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001339 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001340
1341 // Second finger down on the right window
1342 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001343 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001344 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001345 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1346 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001347 .build();
1348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001349 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001350 InputEventInjectionSync::WAIT_FOR_RESULT))
1351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1352
1353 leftWindow->consumeMotionMove();
1354 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001355 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1356 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001357 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001358
1359 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001360 mDispatcher->onWindowInfosChanged(
1361 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001362 leftWindow->consumeMotionCancel();
1363 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001364 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001365
1366 // The pointer that's still down on the right window moves, and goes to the right window only.
1367 // As far as the dispatcher's concerned though, both pointers are still present.
1368 const MotionEvent secondFingerMoveEvent =
1369 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1370 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001371 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1372 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001373 .build();
1374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001375 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001376 InputEventInjectionSync::WAIT_FOR_RESULT));
1377 rightWindow->consumeMotionMove();
1378
1379 leftWindow->assertNoEvents();
1380 rightWindow->assertNoEvents();
1381 wallpaperWindow->assertNoEvents();
1382}
1383
Arthur Hungc539dbb2022-12-08 07:45:36 +00001384/**
1385 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1386 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1387 * The right window should receive ACTION_DOWN.
1388 */
1389TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001390 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001391 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1392 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001393 leftWindow->setFrame(Rect(0, 0, 200, 200));
1394 leftWindow->setDupTouchToWallpaper(true);
1395 leftWindow->setSlippery(true);
1396
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001397 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1398 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001399 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001400
1401 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001402 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1403 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001404 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001405
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001406 mDispatcher->onWindowInfosChanged(
1407 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1408 {},
1409 0,
1410 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001411
Arthur Hungc539dbb2022-12-08 07:45:36 +00001412 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001414 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1415 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001416 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001417
1418 // Both foreground window and its wallpaper should receive the touch down
1419 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001420 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001421
Arthur Hungc539dbb2022-12-08 07:45:36 +00001422 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001424 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001425 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1427
Arthur Hungc539dbb2022-12-08 07:45:36 +00001428 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001429 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1430 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001431}
1432
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001433/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001434 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1435 * interactive, it might stop sending this flag.
1436 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1437 * to have a consistent input stream.
1438 *
1439 * Test procedure:
1440 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1441 * DOWN (new gesture).
1442 *
1443 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1444 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1445 *
1446 * We technically just need a single window here, but we are using two windows (spy on top and a
1447 * regular window below) to emulate the actual situation where it happens on the device.
1448 */
1449TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001451 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1452 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001453 spyWindow->setFrame(Rect(0, 0, 200, 200));
1454 spyWindow->setTrustedOverlay(true);
1455 spyWindow->setSpy(true);
1456
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001457 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1458 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001459 window->setFrame(Rect(0, 0, 200, 200));
1460
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001461 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001462 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001463
1464 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001465 mDispatcher->notifyMotion(
1466 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1467 .deviceId(touchDeviceId)
1468 .policyFlags(DEFAULT_POLICY_FLAGS)
1469 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1470 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001471
Prabir Pradhan678438e2023-04-13 19:32:51 +00001472 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1473 .deviceId(touchDeviceId)
1474 .policyFlags(DEFAULT_POLICY_FLAGS)
1475 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1476 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1477 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001478 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1479 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1480 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1481 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1482
1483 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001484 mDispatcher->notifyMotion(
1485 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1486 .deviceId(touchDeviceId)
1487 .policyFlags(0)
1488 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1489 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1490 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001491 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1492 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1493
1494 // We don't need to reset the device to reproduce the issue, but the reset event typically
1495 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001496 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001497
1498 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001499 mDispatcher->notifyMotion(
1500 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1501 .deviceId(touchDeviceId)
1502 .policyFlags(DEFAULT_POLICY_FLAGS)
1503 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1504 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001505 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1506 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1507
1508 // No more events
1509 spyWindow->assertNoEvents();
1510 window->assertNoEvents();
1511}
1512
1513/**
Linnan Li907ae732023-09-05 17:14:21 +08001514 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1515 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1516 * interactive, it might stop sending this flag.
1517 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1518 * the consistency of the hover event in this case.
1519 *
1520 * Test procedure:
1521 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1522 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1523 *
1524 * We expect to receive two full streams of hover events.
1525 */
1526TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1528
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001529 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1530 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001531 window->setFrame(Rect(0, 0, 300, 300));
1532
1533 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1534
1535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1536 .policyFlags(DEFAULT_POLICY_FLAGS)
1537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1538 .build());
1539 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1540
1541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1542 .policyFlags(DEFAULT_POLICY_FLAGS)
1543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1544 .build());
1545 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1546
1547 // Send hover exit without the default policy flags.
1548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1549 .policyFlags(0)
1550 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1551 .build());
1552
1553 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1554
1555 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1556 // right event.
1557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1558 .policyFlags(DEFAULT_POLICY_FLAGS)
1559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1560 .build());
1561 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1562
1563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1564 .policyFlags(DEFAULT_POLICY_FLAGS)
1565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1566 .build());
1567 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1568
1569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1570 .policyFlags(DEFAULT_POLICY_FLAGS)
1571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1572 .build());
1573 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1574}
1575
1576/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001577 * Two windows: a window on the left and a window on the right.
1578 * Mouse is hovered from the right window into the left window.
1579 * Next, we tap on the left window, where the cursor was last seen.
1580 * The second tap is done onto the right window.
1581 * The mouse and tap are from two different devices.
1582 * We technically don't need to set the downtime / eventtime for these events, but setting these
1583 * explicitly helps during debugging.
1584 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1585 * In the buggy implementation, a tap on the right window would cause a crash.
1586 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001587TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1588 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1589
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001591 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1592 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001593 leftWindow->setFrame(Rect(0, 0, 200, 200));
1594
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001595 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1596 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001597 rightWindow->setFrame(Rect(200, 0, 400, 200));
1598
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001599 mDispatcher->onWindowInfosChanged(
1600 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001601 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1602 // stale.
1603 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1604 const int32_t mouseDeviceId = 6;
1605 const int32_t touchDeviceId = 4;
1606 // Move the cursor from right
1607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001608 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001609 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1610 AINPUT_SOURCE_MOUSE)
1611 .deviceId(mouseDeviceId)
1612 .downTime(baseTime + 10)
1613 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001615 .build()));
1616 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1617
1618 // .. to the left window
1619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001620 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001621 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1622 AINPUT_SOURCE_MOUSE)
1623 .deviceId(mouseDeviceId)
1624 .downTime(baseTime + 10)
1625 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001626 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001627 .build()));
1628 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1629 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1630 // Now tap the left window
1631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001632 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001633 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1634 AINPUT_SOURCE_TOUCHSCREEN)
1635 .deviceId(touchDeviceId)
1636 .downTime(baseTime + 40)
1637 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001638 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001639 .build()));
1640 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1641 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1642
1643 // release tap
1644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001645 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001646 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1647 AINPUT_SOURCE_TOUCHSCREEN)
1648 .deviceId(touchDeviceId)
1649 .downTime(baseTime + 40)
1650 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001651 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001652 .build()));
1653 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1654
1655 // Tap the window on the right
1656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001657 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001658 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1659 AINPUT_SOURCE_TOUCHSCREEN)
1660 .deviceId(touchDeviceId)
1661 .downTime(baseTime + 60)
1662 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001663 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001664 .build()));
1665 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1666
1667 // release tap
1668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001669 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001670 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1671 AINPUT_SOURCE_TOUCHSCREEN)
1672 .deviceId(touchDeviceId)
1673 .downTime(baseTime + 60)
1674 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001675 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001676 .build()));
1677 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1678
1679 // No more events
1680 leftWindow->assertNoEvents();
1681 rightWindow->assertNoEvents();
1682}
1683
1684/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001685 * Two windows: a window on the left and a window on the right.
1686 * Mouse is hovered from the right window into the left window.
1687 * Next, we tap on the left window, where the cursor was last seen.
1688 * The second tap is done onto the right window.
1689 * The mouse and tap are from two different devices.
1690 * We technically don't need to set the downtime / eventtime for these events, but setting these
1691 * explicitly helps during debugging.
1692 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1693 * In the buggy implementation, a tap on the right window would cause a crash.
1694 */
1695TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1696 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1697
1698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001699 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1700 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001701 leftWindow->setFrame(Rect(0, 0, 200, 200));
1702
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001703 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1704 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001705 rightWindow->setFrame(Rect(200, 0, 400, 200));
1706
1707 mDispatcher->onWindowInfosChanged(
1708 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1709 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1710 // stale.
1711 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1712 const int32_t mouseDeviceId = 6;
1713 const int32_t touchDeviceId = 4;
1714 // Move the cursor from right
1715 mDispatcher->notifyMotion(
1716 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1717 .deviceId(mouseDeviceId)
1718 .downTime(baseTime + 10)
1719 .eventTime(baseTime + 20)
1720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1721 .build());
1722 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1723
1724 // .. to the left window
1725 mDispatcher->notifyMotion(
1726 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1727 .deviceId(mouseDeviceId)
1728 .downTime(baseTime + 10)
1729 .eventTime(baseTime + 30)
1730 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1731 .build());
1732 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1733 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1734 // Now tap the left window
1735 mDispatcher->notifyMotion(
1736 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1737 .deviceId(touchDeviceId)
1738 .downTime(baseTime + 40)
1739 .eventTime(baseTime + 40)
1740 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1741 .build());
1742 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1743
1744 // release tap
1745 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1746 .deviceId(touchDeviceId)
1747 .downTime(baseTime + 40)
1748 .eventTime(baseTime + 50)
1749 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1750 .build());
1751 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1752
1753 // Tap the window on the right
1754 mDispatcher->notifyMotion(
1755 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1756 .deviceId(touchDeviceId)
1757 .downTime(baseTime + 60)
1758 .eventTime(baseTime + 60)
1759 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1760 .build());
1761 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1762
1763 // release tap
1764 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1765 .deviceId(touchDeviceId)
1766 .downTime(baseTime + 60)
1767 .eventTime(baseTime + 70)
1768 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1769 .build());
1770 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1771
1772 // No more events
1773 leftWindow->assertNoEvents();
1774 rightWindow->assertNoEvents();
1775}
1776
1777/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001778 * Start hovering in a window. While this hover is still active, make another window appear on top.
1779 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1780 * While the top window is present, the hovering is stopped.
1781 * Later, hovering gets resumed again.
1782 * Ensure that new hover gesture is handled correctly.
1783 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1784 * to the window that's currently being hovered over.
1785 */
1786TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1789 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001790 window->setFrame(Rect(0, 0, 200, 200));
1791
1792 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001793 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001794
1795 // Start hovering in the window
1796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1798 .build());
1799 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1800
1801 // Now, an obscuring window appears!
1802 sp<FakeWindowHandle> obscuringWindow =
1803 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001804 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001805 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001806 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1807 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1808 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1809 obscuringWindow->setNoInputChannel(true);
1810 obscuringWindow->setFocusable(false);
1811 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001812 mDispatcher->onWindowInfosChanged(
1813 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001814
1815 // While this new obscuring window is present, the hovering is stopped
1816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1817 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1818 .build());
1819 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1820
1821 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001822 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001823
1824 // And a new hover gesture starts.
1825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1827 .build());
1828 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1829}
1830
1831/**
1832 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1833 * the obscuring window.
1834 */
1835TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1836 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001837 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1838 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001839 window->setFrame(Rect(0, 0, 200, 200));
1840
1841 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001843
1844 // Start hovering in the window
1845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1846 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1847 .build());
1848 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1849
1850 // Now, an obscuring window appears!
1851 sp<FakeWindowHandle> obscuringWindow =
1852 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001853 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001854 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001855 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1856 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1857 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1858 obscuringWindow->setNoInputChannel(true);
1859 obscuringWindow->setFocusable(false);
1860 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001861 mDispatcher->onWindowInfosChanged(
1862 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001863
1864 // While this new obscuring window is present, the hovering continues. The event can't go to the
1865 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1866 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1867 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1868 .build());
1869 obscuringWindow->assertNoEvents();
1870 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1871
1872 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001874
1875 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1876 // so it should generate a HOVER_ENTER
1877 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1878 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1879 .build());
1880 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1881
1882 // Now the MOVE should be getting dispatched normally
1883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1884 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1885 .build());
1886 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1887}
1888
1889/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001890 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1891 * events are delivered to the window.
1892 */
1893TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001895 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1896 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001897 window->setFrame(Rect(0, 0, 200, 200));
1898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1899
1900 // Start hovering in the window
1901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1902 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1903 .build());
1904 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1905
1906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1907 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1908 .build());
1909 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1910
1911 // Scroll with the mouse
1912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1913 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1914 .build());
1915 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1916}
1917
1918using InputDispatcherMultiDeviceTest = InputDispatcherTest;
1919
1920/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001921 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1922 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001923 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001924TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001925 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001927 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1928 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001929 window->setFrame(Rect(0, 0, 200, 200));
1930
1931 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1932
1933 constexpr int32_t touchDeviceId = 4;
1934 constexpr int32_t stylusDeviceId = 2;
1935
1936 // Stylus down
1937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1938 .deviceId(stylusDeviceId)
1939 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1940 .build());
1941 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1942
1943 // Touch down
1944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1945 .deviceId(touchDeviceId)
1946 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1947 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001948
1949 // Touch move
1950 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1951 .deviceId(touchDeviceId)
1952 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1953 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001954 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001955
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001956 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1958 .deviceId(stylusDeviceId)
1959 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
1960 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001961 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
1962 WithCoords(101, 111)));
1963
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001964 window->assertNoEvents();
1965}
1966
1967/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001968 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1969 * touch is not dropped, because multiple devices are allowed to be active in the same window.
1970 */
1971TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
1972 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001974 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1975 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001976 window->setFrame(Rect(0, 0, 200, 200));
1977
1978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1979
1980 constexpr int32_t touchDeviceId = 4;
1981 constexpr int32_t stylusDeviceId = 2;
1982
1983 // Stylus down
1984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1985 .deviceId(stylusDeviceId)
1986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1987 .build());
1988 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1989
1990 // Touch down
1991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1992 .deviceId(touchDeviceId)
1993 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1994 .build());
1995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
1996
1997 // Touch move
1998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1999 .deviceId(touchDeviceId)
2000 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2001 .build());
2002 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2003
2004 // Stylus move
2005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2006 .deviceId(stylusDeviceId)
2007 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2008 .build());
2009 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2010 WithCoords(101, 111)));
2011
2012 window->assertNoEvents();
2013}
2014
2015/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002016 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002017 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002018 * Similar test as above, but with added SPY window.
2019 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002020TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002021 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002023 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2024 ui::LogicalDisplayId::DEFAULT);
2025 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2026 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002027 spyWindow->setFrame(Rect(0, 0, 200, 200));
2028 spyWindow->setTrustedOverlay(true);
2029 spyWindow->setSpy(true);
2030 window->setFrame(Rect(0, 0, 200, 200));
2031
2032 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2033
2034 constexpr int32_t touchDeviceId = 4;
2035 constexpr int32_t stylusDeviceId = 2;
2036
2037 // Stylus down
2038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2039 .deviceId(stylusDeviceId)
2040 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2041 .build());
2042 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2043 spyWindow->consumeMotionEvent(
2044 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2045
2046 // Touch down
2047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2048 .deviceId(touchDeviceId)
2049 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2050 .build());
2051
2052 // Touch move
2053 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2054 .deviceId(touchDeviceId)
2055 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2056 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002057
2058 // Touch is ignored because stylus is already down
2059
2060 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2062 .deviceId(stylusDeviceId)
2063 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2064 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002065 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2066 WithCoords(101, 111)));
2067 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2068 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002069
2070 window->assertNoEvents();
2071 spyWindow->assertNoEvents();
2072}
2073
2074/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002075 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2076 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2077 * Similar test as above, but with added SPY window.
2078 */
2079TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2080 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002082 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2083 ui::LogicalDisplayId::DEFAULT);
2084 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2085 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002086 spyWindow->setFrame(Rect(0, 0, 200, 200));
2087 spyWindow->setTrustedOverlay(true);
2088 spyWindow->setSpy(true);
2089 window->setFrame(Rect(0, 0, 200, 200));
2090
2091 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2092
2093 constexpr int32_t touchDeviceId = 4;
2094 constexpr int32_t stylusDeviceId = 2;
2095
2096 // Stylus down
2097 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2098 .deviceId(stylusDeviceId)
2099 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2100 .build());
2101 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2102 spyWindow->consumeMotionEvent(
2103 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2104
2105 // Touch down
2106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2107 .deviceId(touchDeviceId)
2108 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2109 .build());
2110 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2111 spyWindow->consumeMotionEvent(
2112 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2113
2114 // Touch move
2115 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2116 .deviceId(touchDeviceId)
2117 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2118 .build());
2119 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2120 spyWindow->consumeMotionEvent(
2121 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2122
2123 // Subsequent stylus movements are delivered correctly
2124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2125 .deviceId(stylusDeviceId)
2126 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2127 .build());
2128 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2129 WithCoords(101, 111)));
2130 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2131 WithCoords(101, 111)));
2132
2133 window->assertNoEvents();
2134 spyWindow->assertNoEvents();
2135}
2136
2137/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002138 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002139 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002140 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002141TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002142 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002144 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2145 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002146 window->setFrame(Rect(0, 0, 200, 200));
2147
2148 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2149
2150 constexpr int32_t touchDeviceId = 4;
2151 constexpr int32_t stylusDeviceId = 2;
2152
2153 // Stylus down on the window
2154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2155 .deviceId(stylusDeviceId)
2156 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2157 .build());
2158 window->consumeMotionEvent(
2159 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2160
2161 // Touch down on window
2162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2163 .deviceId(touchDeviceId)
2164 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2165 .build());
2166 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2167 .deviceId(touchDeviceId)
2168 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2169 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002170
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002171 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002172
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002173 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002174 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2175 .deviceId(stylusDeviceId)
2176 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2177 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002178 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2179 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002180
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002181 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2183 .deviceId(touchDeviceId)
2184 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2185 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002186 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002187}
2188
2189/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002190 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2191 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2192 */
2193TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2194 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002196 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2197 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002198 window->setFrame(Rect(0, 0, 200, 200));
2199
2200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2201
2202 constexpr int32_t touchDeviceId = 4;
2203 constexpr int32_t stylusDeviceId = 2;
2204
2205 // Stylus down on the window
2206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2207 .deviceId(stylusDeviceId)
2208 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2209 .build());
2210 window->consumeMotionEvent(
2211 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2212
2213 // Touch down on window
2214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2215 .deviceId(touchDeviceId)
2216 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2217 .build());
2218 // Touch move on window
2219 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2221 .deviceId(touchDeviceId)
2222 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2223 .build());
2224 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2225
2226 // Subsequent stylus movements are delivered correctly
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2228 .deviceId(stylusDeviceId)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2230 .build());
2231 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2232 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2233
2234 // and subsequent touches continue to work
2235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2236 .deviceId(touchDeviceId)
2237 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2238 .build());
2239 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2240 window->assertNoEvents();
2241}
2242
2243/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002244 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002245 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002246 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002247TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002248 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002249 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002250 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2251 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002252 window->setFrame(Rect(0, 0, 200, 200));
2253
2254 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2255
2256 constexpr int32_t touchDeviceId = 4;
2257 constexpr int32_t stylusDeviceId = 2;
2258
2259 // Touch down on window
2260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2261 .deviceId(touchDeviceId)
2262 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2263 .build());
2264 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2265 .deviceId(touchDeviceId)
2266 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2267 .build());
2268 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2269 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2270
2271 // Stylus hover on the window
2272 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2273 .deviceId(stylusDeviceId)
2274 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2275 .build());
2276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2277 .deviceId(stylusDeviceId)
2278 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2279 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002280 // Stylus hover movement causes touch to be canceled
2281 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2282 WithCoords(141, 146)));
2283 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2284 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2285 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2286 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002287
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002288 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002289 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2290 .deviceId(touchDeviceId)
2291 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2292 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002293
2294 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002295}
2296
2297/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002298 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2299 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2300 */
2301TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2302 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2303 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002304 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2305 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002306 window->setFrame(Rect(0, 0, 200, 200));
2307
2308 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2309
2310 constexpr int32_t touchDeviceId = 4;
2311 constexpr int32_t stylusDeviceId = 2;
2312
2313 // Touch down on window
2314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2315 .deviceId(touchDeviceId)
2316 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2317 .build());
2318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2319 .deviceId(touchDeviceId)
2320 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2321 .build());
2322 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2323 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2324
2325 // Stylus hover on the window
2326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2327 .deviceId(stylusDeviceId)
2328 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2329 .build());
2330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2331 .deviceId(stylusDeviceId)
2332 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2333 .build());
2334 // Stylus hover movement is received normally
2335 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2336 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2337 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2338 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2339
2340 // Subsequent touch movements also work
2341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2342 .deviceId(touchDeviceId)
2343 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2344 .build());
2345 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2346 WithCoords(142, 147)));
2347
2348 window->assertNoEvents();
2349}
2350
2351/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002352 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2353 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2354 * become active.
2355 */
2356TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002357 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002359 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2360 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002361 window->setFrame(Rect(0, 0, 200, 200));
2362
2363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2364
2365 constexpr int32_t stylusDeviceId1 = 3;
2366 constexpr int32_t stylusDeviceId2 = 5;
2367
2368 // Touch down on window
2369 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2370 .deviceId(stylusDeviceId1)
2371 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2372 .build());
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2374 .deviceId(stylusDeviceId1)
2375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2376 .build());
2377 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2378 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2379
2380 // Second stylus down
2381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2382 .deviceId(stylusDeviceId2)
2383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2384 .build());
2385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2386 .deviceId(stylusDeviceId2)
2387 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2388 .build());
2389
2390 // First stylus is canceled, second one takes over.
2391 window->consumeMotionEvent(
2392 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2393 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2394 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2395
2396 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2397 .deviceId(stylusDeviceId1)
2398 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2399 .build());
2400 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002401 window->assertNoEvents();
2402}
2403
2404/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002405 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2406 * both stylus devices can function simultaneously.
2407 */
2408TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2409 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002411 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2412 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002413 window->setFrame(Rect(0, 0, 200, 200));
2414
2415 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2416
2417 constexpr int32_t stylusDeviceId1 = 3;
2418 constexpr int32_t stylusDeviceId2 = 5;
2419
2420 // Touch down on window
2421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2422 .deviceId(stylusDeviceId1)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2424 .build());
2425 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2426 .deviceId(stylusDeviceId1)
2427 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2428 .build());
2429 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2430 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2431
2432 // Second stylus down
2433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2434 .deviceId(stylusDeviceId2)
2435 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2436 .build());
2437 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2438 .deviceId(stylusDeviceId2)
2439 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2440 .build());
2441 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2442 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2443
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2445 .deviceId(stylusDeviceId1)
2446 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2447 .build());
2448 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2449 window->assertNoEvents();
2450}
2451
2452/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002453 * One window. Touch down on the window. Then, stylus down on the window from another device.
2454 * Ensure that is canceled, because stylus down should be preferred over touch.
2455 */
2456TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002457 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002458 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002459 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2460 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002461 window->setFrame(Rect(0, 0, 200, 200));
2462
2463 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2464
2465 constexpr int32_t touchDeviceId = 4;
2466 constexpr int32_t stylusDeviceId = 2;
2467
2468 // Touch down on window
2469 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2470 .deviceId(touchDeviceId)
2471 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2472 .build());
2473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2474 .deviceId(touchDeviceId)
2475 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2476 .build());
2477 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2478 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2479
2480 // Stylus down on the window
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2482 .deviceId(stylusDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2486 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2487
2488 // Subsequent stylus movements are delivered correctly
2489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2490 .deviceId(stylusDeviceId)
2491 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2492 .build());
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2494 WithCoords(101, 111)));
2495}
2496
2497/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002498 * One window. Touch down on the window. Then, stylus down on the window from another device.
2499 * Ensure that both touch and stylus are functioning independently.
2500 */
2501TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2502 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002504 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2505 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002506 window->setFrame(Rect(0, 0, 200, 200));
2507
2508 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2509
2510 constexpr int32_t touchDeviceId = 4;
2511 constexpr int32_t stylusDeviceId = 2;
2512
2513 // Touch down on window
2514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2515 .deviceId(touchDeviceId)
2516 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2517 .build());
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2521 .build());
2522 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2523 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2524
2525 // Stylus down on the window
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2527 .deviceId(stylusDeviceId)
2528 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2529 .build());
2530 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2531
2532 // Subsequent stylus movements are delivered correctly
2533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2534 .deviceId(stylusDeviceId)
2535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2536 .build());
2537 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2538 WithCoords(101, 111)));
2539
2540 // Touch continues to work too
2541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2542 .deviceId(touchDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2544 .build());
2545 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2546}
2547
2548/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002549 * Two windows: a window on the left and a window on the right.
2550 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2551 * down. Then, on the left window, also place second touch pointer down.
2552 * This test tries to reproduce a crash.
2553 * In the buggy implementation, second pointer down on the left window would cause a crash.
2554 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002555TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2556 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002558 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2559 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002560 leftWindow->setFrame(Rect(0, 0, 200, 200));
2561
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002562 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2563 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002564 rightWindow->setFrame(Rect(200, 0, 400, 200));
2565
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002566 mDispatcher->onWindowInfosChanged(
2567 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002568
2569 const int32_t touchDeviceId = 4;
2570 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002571
2572 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2574 .deviceId(mouseDeviceId)
2575 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2576 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002577 leftWindow->consumeMotionEvent(
2578 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2579
2580 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2582 .deviceId(mouseDeviceId)
2583 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2584 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2585 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002586
2587 leftWindow->consumeMotionEvent(
2588 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2589 leftWindow->consumeMotionEvent(
2590 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2591
Prabir Pradhan678438e2023-04-13 19:32:51 +00002592 mDispatcher->notifyMotion(
2593 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2594 .deviceId(mouseDeviceId)
2595 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2596 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2597 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2598 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002599 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2600
2601 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2603 .deviceId(touchDeviceId)
2604 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2605 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002606 leftWindow->assertNoEvents();
2607
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002608 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2609
2610 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002611 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2612 .deviceId(touchDeviceId)
2613 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2614 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2615 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002616 // Since this is now a new splittable pointer going down on the left window, and it's coming
2617 // from a different device, the current gesture in the left window (pointer down) should first
2618 // be canceled.
2619 leftWindow->consumeMotionEvent(
2620 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002621 leftWindow->consumeMotionEvent(
2622 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2623 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2624 // current implementation.
2625 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2626 rightWindow->consumeMotionEvent(
2627 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2628
2629 leftWindow->assertNoEvents();
2630 rightWindow->assertNoEvents();
2631}
2632
2633/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002634 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002635 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2636 * down. Then, on the left window, also place second touch pointer down.
2637 * This test tries to reproduce a crash.
2638 * In the buggy implementation, second pointer down on the left window would cause a crash.
2639 */
2640TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2641 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002643 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2644 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002645 leftWindow->setFrame(Rect(0, 0, 200, 200));
2646
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002647 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2648 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002649 rightWindow->setFrame(Rect(200, 0, 400, 200));
2650
2651 mDispatcher->onWindowInfosChanged(
2652 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2653
2654 const int32_t touchDeviceId = 4;
2655 const int32_t mouseDeviceId = 6;
2656
2657 // Start hovering over the left window
2658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2659 .deviceId(mouseDeviceId)
2660 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2661 .build());
2662 leftWindow->consumeMotionEvent(
2663 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2664
2665 // Mouse down on left window
2666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2667 .deviceId(mouseDeviceId)
2668 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2669 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2670 .build());
2671
2672 leftWindow->consumeMotionEvent(
2673 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2674 leftWindow->consumeMotionEvent(
2675 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2676
2677 mDispatcher->notifyMotion(
2678 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2679 .deviceId(mouseDeviceId)
2680 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2681 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2682 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2683 .build());
2684 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2685
2686 // First touch pointer down on right window
2687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2688 .deviceId(touchDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2690 .build());
2691 leftWindow->assertNoEvents();
2692
2693 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2694
2695 // Second touch pointer down on left window
2696 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2697 .deviceId(touchDeviceId)
2698 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2699 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2700 .build());
2701 // Since this is now a new splittable pointer going down on the left window, and it's coming
2702 // from a different device, it will be split and delivered to left window separately.
2703 leftWindow->consumeMotionEvent(
2704 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2705 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2706 // current implementation.
2707 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2708 rightWindow->consumeMotionEvent(
2709 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2710
2711 leftWindow->assertNoEvents();
2712 rightWindow->assertNoEvents();
2713}
2714
2715/**
2716 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002717 * Mouse is hovered on the left window and stylus is hovered on the right window.
2718 */
2719TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002721 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2722 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002723 leftWindow->setFrame(Rect(0, 0, 200, 200));
2724
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002725 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2726 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002727 rightWindow->setFrame(Rect(200, 0, 400, 200));
2728
2729 mDispatcher->onWindowInfosChanged(
2730 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2731
2732 const int32_t stylusDeviceId = 3;
2733 const int32_t mouseDeviceId = 6;
2734
2735 // Start hovering over the left window
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2737 .deviceId(mouseDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2739 .build());
2740 leftWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2742
2743 // Stylus hovered on right window
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2745 .deviceId(stylusDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2747 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002748 rightWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2750
2751 // Subsequent HOVER_MOVE events are dispatched correctly.
2752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2753 .deviceId(mouseDeviceId)
2754 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2755 .build());
2756 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002757 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002758
2759 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2760 .deviceId(stylusDeviceId)
2761 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2762 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002763 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002764 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002765
2766 leftWindow->assertNoEvents();
2767 rightWindow->assertNoEvents();
2768}
2769
2770/**
2771 * Three windows: a window on the left and a window on the right.
2772 * And a spy window that's positioned above all of them.
2773 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2774 * Check the stream that's received by the spy.
2775 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002776TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2777 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2779
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002780 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2781 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002782 spyWindow->setFrame(Rect(0, 0, 400, 400));
2783 spyWindow->setTrustedOverlay(true);
2784 spyWindow->setSpy(true);
2785
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002786 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2787 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002788 leftWindow->setFrame(Rect(0, 0, 200, 200));
2789
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002790 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2791 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002792
2793 rightWindow->setFrame(Rect(200, 0, 400, 200));
2794
2795 mDispatcher->onWindowInfosChanged(
2796 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2797
2798 const int32_t stylusDeviceId = 1;
2799 const int32_t touchDeviceId = 2;
2800
2801 // Stylus down on the left window
2802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2803 .deviceId(stylusDeviceId)
2804 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2805 .build());
2806 leftWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2808 spyWindow->consumeMotionEvent(
2809 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2810
2811 // Touch down on the right window
2812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2813 .deviceId(touchDeviceId)
2814 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2815 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002816 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002817 rightWindow->consumeMotionEvent(
2818 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002819
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002820 // Spy window does not receive touch events, because stylus events take precedence, and it
2821 // already has an active stylus gesture.
2822
2823 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2825 .deviceId(stylusDeviceId)
2826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2827 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002828 leftWindow->consumeMotionEvent(
2829 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2830 spyWindow->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002832
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002833 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2835 .deviceId(touchDeviceId)
2836 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2837 .build());
2838 rightWindow->consumeMotionEvent(
2839 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002840
2841 spyWindow->assertNoEvents();
2842 leftWindow->assertNoEvents();
2843 rightWindow->assertNoEvents();
2844}
2845
2846/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002847 * Three windows: a window on the left and a window on the right.
2848 * And a spy window that's positioned above all of them.
2849 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2850 * Check the stream that's received by the spy.
2851 */
2852TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2853 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2855
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002856 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2857 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002858 spyWindow->setFrame(Rect(0, 0, 400, 400));
2859 spyWindow->setTrustedOverlay(true);
2860 spyWindow->setSpy(true);
2861
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002862 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2863 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002864 leftWindow->setFrame(Rect(0, 0, 200, 200));
2865
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002866 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2867 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002868
2869 rightWindow->setFrame(Rect(200, 0, 400, 200));
2870
2871 mDispatcher->onWindowInfosChanged(
2872 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2873
2874 const int32_t stylusDeviceId = 1;
2875 const int32_t touchDeviceId = 2;
2876
2877 // Stylus down on the left window
2878 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2879 .deviceId(stylusDeviceId)
2880 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2881 .build());
2882 leftWindow->consumeMotionEvent(
2883 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2884 spyWindow->consumeMotionEvent(
2885 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2886
2887 // Touch down on the right window
2888 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2889 .deviceId(touchDeviceId)
2890 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2891 .build());
2892 leftWindow->assertNoEvents();
2893 rightWindow->consumeMotionEvent(
2894 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2895 spyWindow->consumeMotionEvent(
2896 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2897
2898 // Stylus movements continue. They should be delivered to the left window and to the spy window
2899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2900 .deviceId(stylusDeviceId)
2901 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2902 .build());
2903 leftWindow->consumeMotionEvent(
2904 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2905 spyWindow->consumeMotionEvent(
2906 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2907
2908 // Further touch MOVE events keep going to the right window and to the spy
2909 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2910 .deviceId(touchDeviceId)
2911 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2912 .build());
2913 rightWindow->consumeMotionEvent(
2914 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2915 spyWindow->consumeMotionEvent(
2916 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2917
2918 spyWindow->assertNoEvents();
2919 leftWindow->assertNoEvents();
2920 rightWindow->assertNoEvents();
2921}
2922
2923/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002924 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2925 * both.
2926 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002927 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002928 * At the same time, left and right should be getting independent streams of hovering and touch,
2929 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002930 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002931TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002932 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2934
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002935 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2936 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002937 spyWindow->setFrame(Rect(0, 0, 400, 400));
2938 spyWindow->setTrustedOverlay(true);
2939 spyWindow->setSpy(true);
2940
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002941 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2942 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002943 leftWindow->setFrame(Rect(0, 0, 200, 200));
2944
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002945 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2946 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002947 rightWindow->setFrame(Rect(200, 0, 400, 200));
2948
2949 mDispatcher->onWindowInfosChanged(
2950 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2951
2952 const int32_t stylusDeviceId = 1;
2953 const int32_t touchDeviceId = 2;
2954
2955 // Stylus hover on the left window
2956 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2957 .deviceId(stylusDeviceId)
2958 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2959 .build());
2960 leftWindow->consumeMotionEvent(
2961 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2962 spyWindow->consumeMotionEvent(
2963 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2964
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002965 // Touch down on the right window. Spy doesn't receive this touch because it already has
2966 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002971 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002972 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002973 rightWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2975
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002976 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002977 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2978 .deviceId(stylusDeviceId)
2979 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2980 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002981 leftWindow->consumeMotionEvent(
2982 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002983 spyWindow->consumeMotionEvent(
2984 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002986 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2988 .deviceId(touchDeviceId)
2989 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2990 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002991 rightWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2993
2994 spyWindow->assertNoEvents();
2995 leftWindow->assertNoEvents();
2996 rightWindow->assertNoEvents();
2997}
2998
2999/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003000 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3001 * both.
3002 * Check hover in left window and touch down in the right window.
3003 * At first, spy should receive hover. Next, spy should receive touch.
3004 * At the same time, left and right should be getting independent streams of hovering and touch,
3005 * respectively.
3006 */
3007TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3008 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3010
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003011 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3012 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003013 spyWindow->setFrame(Rect(0, 0, 400, 400));
3014 spyWindow->setTrustedOverlay(true);
3015 spyWindow->setSpy(true);
3016
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003017 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3018 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003019 leftWindow->setFrame(Rect(0, 0, 200, 200));
3020
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003021 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3022 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003023 rightWindow->setFrame(Rect(200, 0, 400, 200));
3024
3025 mDispatcher->onWindowInfosChanged(
3026 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3027
3028 const int32_t stylusDeviceId = 1;
3029 const int32_t touchDeviceId = 2;
3030
3031 // Stylus hover on the left window
3032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3033 .deviceId(stylusDeviceId)
3034 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3035 .build());
3036 leftWindow->consumeMotionEvent(
3037 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3038 spyWindow->consumeMotionEvent(
3039 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3040
3041 // Touch down on the right window.
3042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3043 .deviceId(touchDeviceId)
3044 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3045 .build());
3046 leftWindow->assertNoEvents();
3047 spyWindow->consumeMotionEvent(
3048 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3049 rightWindow->consumeMotionEvent(
3050 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3051
3052 // Stylus movements continue. They should be delivered to the left window and the spy.
3053 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3054 .deviceId(stylusDeviceId)
3055 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3056 .build());
3057 leftWindow->consumeMotionEvent(
3058 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3059 spyWindow->consumeMotionEvent(
3060 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3061
3062 // Touch movements continue. They should be delivered to the right window and the spy
3063 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3064 .deviceId(touchDeviceId)
3065 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3066 .build());
3067 rightWindow->consumeMotionEvent(
3068 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3069 spyWindow->consumeMotionEvent(
3070 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3071
3072 spyWindow->assertNoEvents();
3073 leftWindow->assertNoEvents();
3074 rightWindow->assertNoEvents();
3075}
3076
3077/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003078 * On a single window, use two different devices: mouse and touch.
3079 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3080 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3081 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3082 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3083 * represent a new gesture.
3084 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003085TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3086 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003088 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3089 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003090 window->setFrame(Rect(0, 0, 400, 400));
3091
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003092 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003093
3094 const int32_t touchDeviceId = 4;
3095 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003096
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003097 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3099 .deviceId(touchDeviceId)
3100 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3101 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003102 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003103 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3104 .deviceId(touchDeviceId)
3105 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3106 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3107 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003109 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3110 .deviceId(touchDeviceId)
3111 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3112 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3113 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3115 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3116 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3117
3118 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3120 .deviceId(mouseDeviceId)
3121 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3122 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3123 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003124
3125 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003126 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3128
Prabir Pradhan678438e2023-04-13 19:32:51 +00003129 mDispatcher->notifyMotion(
3130 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3131 .deviceId(mouseDeviceId)
3132 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3133 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3134 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3137
3138 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003139 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3140 .deviceId(touchDeviceId)
3141 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3142 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3143 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003144 // Since we already canceled this touch gesture, it will be ignored until a completely new
3145 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3146 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3147 // However, mouse movements should continue to work.
3148 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3149 .deviceId(mouseDeviceId)
3150 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3151 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3152 .build());
3153 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3154
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 window->assertNoEvents();
3156}
3157
3158/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003159 * On a single window, use two different devices: mouse and touch.
3160 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3161 * Mouse is clicked next, which should not interfere with the touch stream.
3162 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3163 * delivered correctly.
3164 */
3165TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3166 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003168 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3169 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003170 window->setFrame(Rect(0, 0, 400, 400));
3171
3172 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3173
3174 const int32_t touchDeviceId = 4;
3175 const int32_t mouseDeviceId = 6;
3176
3177 // First touch pointer down
3178 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3179 .deviceId(touchDeviceId)
3180 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3181 .build());
3182 // Second touch pointer down
3183 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3184 .deviceId(touchDeviceId)
3185 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3186 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3187 .build());
3188 // First touch pointer lifts. The second one remains down
3189 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3193 .build());
3194 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3195 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3196 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3197
3198 // Mouse down
3199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3200 .deviceId(mouseDeviceId)
3201 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3202 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3203 .build());
3204
3205 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3206
3207 mDispatcher->notifyMotion(
3208 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3209 .deviceId(mouseDeviceId)
3210 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3211 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3212 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3213 .build());
3214 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3215
3216 // Second touch pointer down.
3217 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3218 .deviceId(touchDeviceId)
3219 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3220 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3221 .build());
3222 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3223 WithPointerCount(2u)));
3224
3225 // Mouse movements should continue to work
3226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3227 .deviceId(mouseDeviceId)
3228 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3229 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3230 .build());
3231 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3232
3233 window->assertNoEvents();
3234}
3235
3236/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003237 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3238 * the injected event.
3239 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003240TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3241 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003242 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003243 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3244 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003245 window->setFrame(Rect(0, 0, 400, 400));
3246
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003247 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003248
3249 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003250 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3251 // completion.
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003254 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3255 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003257 .build()));
3258 window->consumeMotionEvent(
3259 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3260
3261 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3262 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3264 .deviceId(touchDeviceId)
3265 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3266 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003267
3268 window->consumeMotionEvent(
3269 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3270 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3271}
3272
3273/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003274 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3275 * parallel to the injected event.
3276 */
3277TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3278 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003280 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3281 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003282 window->setFrame(Rect(0, 0, 400, 400));
3283
3284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3285
3286 const int32_t touchDeviceId = 4;
3287 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3288 // completion.
3289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3290 injectMotionEvent(*mDispatcher,
3291 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3292 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3294 .build()));
3295 window->consumeMotionEvent(
3296 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3297
3298 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3299 // allowed through.
3300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3301 .deviceId(touchDeviceId)
3302 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3303 .build());
3304 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3305}
3306
3307/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003308 * This test is similar to the test above, but the sequence of injected events is different.
3309 *
3310 * Two windows: a window on the left and a window on the right.
3311 * Mouse is hovered over the left window.
3312 * Next, we tap on the left window, where the cursor was last seen.
3313 *
3314 * After that, we inject one finger down onto the right window, and then a second finger down onto
3315 * the left window.
3316 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3317 * window (first), and then another on the left window (second).
3318 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3319 * In the buggy implementation, second finger down on the left window would cause a crash.
3320 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003321TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3322 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003324 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3325 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003326 leftWindow->setFrame(Rect(0, 0, 200, 200));
3327
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003328 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3329 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003330 rightWindow->setFrame(Rect(200, 0, 400, 200));
3331
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003332 mDispatcher->onWindowInfosChanged(
3333 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003334
3335 const int32_t mouseDeviceId = 6;
3336 const int32_t touchDeviceId = 4;
3337 // Hover over the left window. Keep the cursor there.
3338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3341 AINPUT_SOURCE_MOUSE)
3342 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003343 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003344 .build()));
3345 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3346
3347 // Tap on left window
3348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003349 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003350 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3351 AINPUT_SOURCE_TOUCHSCREEN)
3352 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003353 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003354 .build()));
3355
3356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003358 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3359 AINPUT_SOURCE_TOUCHSCREEN)
3360 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003361 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003362 .build()));
3363 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3364 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3365 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3366
3367 // First finger down on right window
3368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003369 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003370 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3371 AINPUT_SOURCE_TOUCHSCREEN)
3372 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003373 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003374 .build()));
3375 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3376
3377 // Second finger down on the left window
3378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003379 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003380 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3381 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003382 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3383 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003384 .build()));
3385 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3386 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3387
3388 // No more events
3389 leftWindow->assertNoEvents();
3390 rightWindow->assertNoEvents();
3391}
3392
3393/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003394 * This test is similar to the test above, but the sequence of injected events is different.
3395 *
3396 * Two windows: a window on the left and a window on the right.
3397 * Mouse is hovered over the left window.
3398 * Next, we tap on the left window, where the cursor was last seen.
3399 *
3400 * After that, we send one finger down onto the right window, and then a second finger down onto
3401 * the left window.
3402 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3403 * window (first), and then another on the left window (second).
3404 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3405 * In the buggy implementation, second finger down on the left window would cause a crash.
3406 */
3407TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3408 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003410 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3411 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003412 leftWindow->setFrame(Rect(0, 0, 200, 200));
3413
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003414 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3415 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003416 rightWindow->setFrame(Rect(200, 0, 400, 200));
3417
3418 mDispatcher->onWindowInfosChanged(
3419 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3420
3421 const int32_t mouseDeviceId = 6;
3422 const int32_t touchDeviceId = 4;
3423 // Hover over the left window. Keep the cursor there.
3424 mDispatcher->notifyMotion(
3425 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3426 .deviceId(mouseDeviceId)
3427 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3428 .build());
3429 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3430
3431 // Tap on left window
3432 mDispatcher->notifyMotion(
3433 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3434 .deviceId(touchDeviceId)
3435 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3436 .build());
3437
3438 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3439 .deviceId(touchDeviceId)
3440 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3441 .build());
3442 leftWindow->consumeMotionEvent(
3443 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3444 leftWindow->consumeMotionEvent(
3445 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3446
3447 // First finger down on right window
3448 mDispatcher->notifyMotion(
3449 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3450 .deviceId(touchDeviceId)
3451 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3452 .build());
3453 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3454
3455 // Second finger down on the left window
3456 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3457 .deviceId(touchDeviceId)
3458 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3459 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3460 .build());
3461 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3462 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3463
3464 // No more events
3465 leftWindow->assertNoEvents();
3466 rightWindow->assertNoEvents();
3467}
3468
3469/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003470 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3471 * While the touch is down, new hover events from the stylus device should be ignored. After the
3472 * touch is gone, stylus hovering should start working again.
3473 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003474TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003475 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003477 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3478 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003479 window->setFrame(Rect(0, 0, 200, 200));
3480
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003481 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003482
3483 const int32_t stylusDeviceId = 5;
3484 const int32_t touchDeviceId = 4;
3485 // Start hovering with stylus
3486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003487 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003488 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003489 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003490 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003491 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003492 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003493
3494 // Finger down on the window
3495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003496 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003497 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003498 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003499 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003500 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003501 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003502
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003503 // Continue hovering with stylus.
3504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003505 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003506 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3507 AINPUT_SOURCE_STYLUS)
3508 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003509 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003510 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003511 // Hovers continue to work
3512 window->consumeMotionEvent(
3513 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003514
3515 // Lift up the finger
3516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003517 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003518 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3519 AINPUT_SOURCE_TOUCHSCREEN)
3520 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003521 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003522 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003523
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003525 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003526 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3527 AINPUT_SOURCE_STYLUS)
3528 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003529 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003530 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003531 window->consumeMotionEvent(
3532 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003533 window->assertNoEvents();
3534}
3535
3536/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003537 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3538 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3539 * check that the stylus hovering continues to work.
3540 */
3541TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3542 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003544 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3545 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003546 window->setFrame(Rect(0, 0, 200, 200));
3547
3548 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3549
3550 const int32_t stylusDeviceId = 5;
3551 const int32_t touchDeviceId = 4;
3552 // Start hovering with stylus
3553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3554 .deviceId(stylusDeviceId)
3555 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3556 .build());
3557 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3558
3559 // Finger down on the window
3560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3561 .deviceId(touchDeviceId)
3562 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3563 .build());
3564 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3565
3566 // Continue hovering with stylus.
3567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3568 .deviceId(stylusDeviceId)
3569 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3570 .build());
3571 // Hovers continue to work
3572 window->consumeMotionEvent(
3573 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3574
3575 // Lift up the finger
3576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3577 .deviceId(touchDeviceId)
3578 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3579 .build());
3580 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3581
3582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3583 .deviceId(stylusDeviceId)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3585 .build());
3586 window->consumeMotionEvent(
3587 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3588 window->assertNoEvents();
3589}
3590
3591/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003592 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3593 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3594 *
3595 * Two windows: one on the left and one on the right.
3596 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3597 * Stylus down on the left window, and then touch down on the right window.
3598 * Check that the right window doesn't get touches while the stylus is down on the left window.
3599 */
3600TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3602 sp<FakeWindowHandle> leftWindow =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003604 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003605 leftWindow->setFrame(Rect(0, 0, 100, 100));
3606
3607 sp<FakeWindowHandle> sbtRightWindow =
3608 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003609 "Stylus blocks touch (right) window",
3610 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003611 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3612 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3613
3614 mDispatcher->onWindowInfosChanged(
3615 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3616
3617 const int32_t stylusDeviceId = 5;
3618 const int32_t touchDeviceId = 4;
3619
3620 // Stylus down in the left window
3621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3623 .deviceId(stylusDeviceId)
3624 .build());
3625 leftWindow->consumeMotionEvent(
3626 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3627
3628 // Finger tap on the right window
3629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3630 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3631 .deviceId(touchDeviceId)
3632 .build());
3633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3634 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3635 .deviceId(touchDeviceId)
3636 .build());
3637
3638 // The touch should be blocked, because stylus is down somewhere else on screen!
3639 sbtRightWindow->assertNoEvents();
3640
3641 // Continue stylus motion, and ensure it's not impacted.
3642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3643 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3644 .deviceId(stylusDeviceId)
3645 .build());
3646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3647 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3648 .deviceId(stylusDeviceId)
3649 .build());
3650 leftWindow->consumeMotionEvent(
3651 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3652 leftWindow->consumeMotionEvent(
3653 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3654
3655 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3656 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3657 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3658 .deviceId(touchDeviceId)
3659 .build());
3660 sbtRightWindow->consumeMotionEvent(
3661 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3662}
3663
3664/**
3665 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3666 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3667 *
3668 * Two windows: one on the left and one on the right.
3669 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3670 * Stylus hover on the left window, and then touch down on the right window.
3671 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3672 */
3673TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3675 sp<FakeWindowHandle> leftWindow =
3676 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003677 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003678 leftWindow->setFrame(Rect(0, 0, 100, 100));
3679
3680 sp<FakeWindowHandle> sbtRightWindow =
3681 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003682 "Stylus blocks touch (right) window",
3683 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003684 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3685 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3686
3687 mDispatcher->onWindowInfosChanged(
3688 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3689
3690 const int32_t stylusDeviceId = 5;
3691 const int32_t touchDeviceId = 4;
3692
3693 // Stylus hover in the left window
3694 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3695 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3696 .deviceId(stylusDeviceId)
3697 .build());
3698 leftWindow->consumeMotionEvent(
3699 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3700
3701 // Finger tap on the right window
3702 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3703 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3704 .deviceId(touchDeviceId)
3705 .build());
3706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3707 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3708 .deviceId(touchDeviceId)
3709 .build());
3710
3711 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3712 sbtRightWindow->assertNoEvents();
3713
3714 // Continue stylus motion, and ensure it's not impacted.
3715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3716 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3717 .deviceId(stylusDeviceId)
3718 .build());
3719 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3720 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3721 .deviceId(stylusDeviceId)
3722 .build());
3723 leftWindow->consumeMotionEvent(
3724 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3725 leftWindow->consumeMotionEvent(
3726 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3727
3728 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3730 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3731 .deviceId(touchDeviceId)
3732 .build());
3733 sbtRightWindow->consumeMotionEvent(
3734 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3735}
3736
3737/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003738 * A spy window above a window with no input channel.
3739 * Start hovering with a stylus device, and then tap with it.
3740 * Ensure spy window receives the entire sequence.
3741 */
3742TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3743 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003744 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3745 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003746 spyWindow->setFrame(Rect(0, 0, 200, 200));
3747 spyWindow->setTrustedOverlay(true);
3748 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3750 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003751 window->setNoInputChannel(true);
3752 window->setFrame(Rect(0, 0, 200, 200));
3753
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003754 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003755
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003756 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3758 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3759 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003760 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3761 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3763 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3764 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003765 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3766
3767 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3769 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3770 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003771 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3772
3773 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3776 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003777 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3778
3779 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003783 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3784 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3787 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003788 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3789
3790 // No more events
3791 spyWindow->assertNoEvents();
3792 window->assertNoEvents();
3793}
3794
3795/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003796 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3797 * rejected. But since we already have an ongoing gesture, this event should be processed.
3798 * This prevents inconsistent events being handled inside the dispatcher.
3799 */
3800TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3802
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003803 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3804 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003805 window->setFrame(Rect(0, 0, 200, 200));
3806
3807 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3808
3809 // Start hovering with stylus
3810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3811 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3812 .build());
3813 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3814
3815 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3816 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3817 .build();
3818 // Make this 'hoverExit' event stale
3819 mFakePolicy->setStaleEventTimeout(100ms);
3820 std::this_thread::sleep_for(100ms);
3821
3822 // It shouldn't be dropped by the dispatcher, even though it's stale.
3823 mDispatcher->notifyMotion(hoverExit);
3824 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3825
3826 // Stylus starts hovering again! There should be no crash.
3827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3828 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3829 .build());
3830 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3831}
3832
3833/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003834 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3835 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3836 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3837 * While the mouse is down, new move events from the touch device should be ignored.
3838 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003839TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3840 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003842 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3843 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003844 spyWindow->setFrame(Rect(0, 0, 200, 200));
3845 spyWindow->setTrustedOverlay(true);
3846 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003847 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3848 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003849 window->setFrame(Rect(0, 0, 200, 200));
3850
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003851 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003852
3853 const int32_t mouseDeviceId = 7;
3854 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003855
3856 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3858 .deviceId(mouseDeviceId)
3859 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3860 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003861 spyWindow->consumeMotionEvent(
3862 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3863 window->consumeMotionEvent(
3864 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3865
3866 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3868 .deviceId(touchDeviceId)
3869 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3870 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003871 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3872 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3873 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3874 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3875
Prabir Pradhan678438e2023-04-13 19:32:51 +00003876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3877 .deviceId(touchDeviceId)
3878 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3879 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003880 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3881 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3882
3883 // Pilfer the stream
3884 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3885 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3886
Prabir Pradhan678438e2023-04-13 19:32:51 +00003887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3888 .deviceId(touchDeviceId)
3889 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3890 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003891 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3892
3893 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3895 .deviceId(mouseDeviceId)
3896 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3897 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3898 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003899
3900 spyWindow->consumeMotionEvent(
3901 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3902 spyWindow->consumeMotionEvent(
3903 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3904 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3905
Prabir Pradhan678438e2023-04-13 19:32:51 +00003906 mDispatcher->notifyMotion(
3907 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3908 .deviceId(mouseDeviceId)
3909 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3910 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3912 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003913 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3914 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3915
3916 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003917 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3918 .deviceId(mouseDeviceId)
3919 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3920 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3921 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003922 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3923 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3924
3925 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3927 .deviceId(touchDeviceId)
3928 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3929 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003930
3931 // No more events
3932 spyWindow->assertNoEvents();
3933 window->assertNoEvents();
3934}
3935
3936/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003937 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3938 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3939 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3940 * While the mouse is down, new move events from the touch device should continue to work.
3941 */
3942TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3943 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003945 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3946 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003947 spyWindow->setFrame(Rect(0, 0, 200, 200));
3948 spyWindow->setTrustedOverlay(true);
3949 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003950 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3951 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003952 window->setFrame(Rect(0, 0, 200, 200));
3953
3954 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3955
3956 const int32_t mouseDeviceId = 7;
3957 const int32_t touchDeviceId = 4;
3958
3959 // Hover a bit with mouse first
3960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3961 .deviceId(mouseDeviceId)
3962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3963 .build());
3964 spyWindow->consumeMotionEvent(
3965 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3966 window->consumeMotionEvent(
3967 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3968
3969 // Start touching
3970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3971 .deviceId(touchDeviceId)
3972 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3973 .build());
3974
3975 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3976 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3977
3978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3979 .deviceId(touchDeviceId)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3981 .build());
3982 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3983 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3984
3985 // Pilfer the stream
3986 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3987 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3988 // Hover is not pilfered! Only touch.
3989
3990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3991 .deviceId(touchDeviceId)
3992 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3993 .build());
3994 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3995
3996 // Mouse down
3997 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3998 .deviceId(mouseDeviceId)
3999 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4000 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4001 .build());
4002
4003 spyWindow->consumeMotionEvent(
4004 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4005 spyWindow->consumeMotionEvent(
4006 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4007 window->consumeMotionEvent(
4008 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4009 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4010
4011 mDispatcher->notifyMotion(
4012 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4013 .deviceId(mouseDeviceId)
4014 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4015 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4016 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4017 .build());
4018 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4019 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4020
4021 // Mouse move!
4022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4023 .deviceId(mouseDeviceId)
4024 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4026 .build());
4027 spyWindow->consumeMotionEvent(
4028 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4029 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4030
4031 // Touch move!
4032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4033 .deviceId(touchDeviceId)
4034 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4035 .build());
4036 spyWindow->consumeMotionEvent(
4037 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4038
4039 // No more events
4040 spyWindow->assertNoEvents();
4041 window->assertNoEvents();
4042}
4043
4044/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004045 * On the display, have a single window, and also an area where there's no window.
4046 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4047 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4048 */
4049TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4051 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004052 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004053
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004054 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004055
4056 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004057 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004058
4059 mDispatcher->waitForIdle();
4060 window->assertNoEvents();
4061
4062 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004063 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004064 mDispatcher->waitForIdle();
4065 window->consumeMotionDown();
4066}
4067
4068/**
4069 * Same test as above, but instead of touching the empty space, the first touch goes to
4070 * non-touchable window.
4071 */
4072TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4074 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004075 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004076 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4077 window1->setTouchable(false);
4078 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004079 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004080 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004082 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004083
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004084 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004085 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004086
4087 mDispatcher->waitForIdle();
4088 window1->assertNoEvents();
4089 window2->assertNoEvents();
4090
4091 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004092 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004093 mDispatcher->waitForIdle();
4094 window2->consumeMotionDown();
4095}
4096
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004097/**
4098 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4099 * to the event time of the first ACTION_DOWN sent to the particular window.
4100 */
4101TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4102 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4103 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004104 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004105 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4106 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004108 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004110 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004111
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004112 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004113 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004114 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004116 const std::unique_ptr<MotionEvent> firstDown =
4117 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4118 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004119 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004120
4121 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004122 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004123 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004124
4125 const std::unique_ptr<MotionEvent> secondDown =
4126 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4127 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4128 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4129 // We currently send MOVE events to all windows receiving a split touch when there is any change
4130 // in the touch state, even when none of the pointers in the split window actually moved.
4131 // Document this behavior in the test.
4132 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004133
4134 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004135 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004136 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004137
4138 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4139 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004140
4141 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004142 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004143 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004144
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004145 window2->consumeMotionEvent(
4146 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4147 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004148
4149 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004150 mDispatcher->notifyMotion(
4151 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004152 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004153
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004154 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4155 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4156
4157 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004158 mDispatcher->notifyMotion(
4159 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004160 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004161
4162 window1->consumeMotionEvent(
4163 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4164 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004165}
4166
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004167/**
4168 * When events are not split, the downTime should be adjusted such that the downTime corresponds
4169 * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
4170 * the event routing because the first window prevents splitting.
4171 */
4172TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
4173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4174 sp<FakeWindowHandle> window1 =
4175 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4176 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4177 window1->setPreventSplitting(true);
4178
4179 sp<FakeWindowHandle> window2 =
4180 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4181 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4182
4183 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4184
4185 // Touch down on the first window
4186 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4187 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4188 .build();
4189 mDispatcher->notifyMotion(downArgs);
4190
4191 window1->consumeMotionEvent(
4192 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4193
4194 // Second window is added
4195 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4196
4197 // Now touch down on the window with another pointer
4198 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4199 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4200 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4201 .downTime(downArgs.downTime)
4202 .build());
4203 window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4204
4205 // Finish the gesture
4206 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4207 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4208 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4209 .downTime(downArgs.downTime)
4210 .build());
4211 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4212 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4213 .downTime(downArgs.downTime)
4214 .build());
4215 window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4216 window1->consumeMotionEvent(
4217 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4218 window2->assertNoEvents();
4219}
4220
4221/**
4222 * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4223 * to the event time of the first ACTION_DOWN sent to the new window.
4224 * If a new window that does not support split appears on the screen and gets touched with the
4225 * second finger, it should not get any events because it doesn't want split touches. At the same
4226 * time, the first window should not get the pointer_down event because it supports split touches
4227 * (and the touch occurred outside of the bounds of window1).
4228 */
4229TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
4230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4231 sp<FakeWindowHandle> window1 =
4232 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4233 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4234
4235 sp<FakeWindowHandle> window2 =
4236 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4237 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4238
4239 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4240
4241 // Touch down on the first window
4242 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4243 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4244 .build();
4245 mDispatcher->notifyMotion(downArgs);
4246
4247 window1->consumeMotionEvent(
4248 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4249
4250 // Second window is added
4251 window2->setPreventSplitting(true);
4252 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4253
4254 // Now touch down on the window with another pointer
4255 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4256 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4257 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4258 .downTime(downArgs.downTime)
4259 .build());
4260 // Event is dropped because window2 doesn't support split touch, and window1 does.
4261
4262 // Complete the gesture
4263 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4264 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4265 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4266 .downTime(downArgs.downTime)
4267 .build());
4268 // A redundant MOVE event is generated that doesn't carry any new information
4269 window1->consumeMotionEvent(
4270 AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4273 .downTime(downArgs.downTime)
4274 .build());
4275
4276 window1->consumeMotionEvent(
4277 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4278 window1->assertNoEvents();
4279 window2->assertNoEvents();
4280}
4281
Garfield Tandf26e862020-07-01 20:18:19 -07004282TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004284 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4285 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004286 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004287 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4288 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004289 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004290
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004291 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004292
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004293 mDispatcher->onWindowInfosChanged(
4294 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004295
4296 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004298 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004299 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4300 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004301 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004302 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004303 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004304
4305 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004307 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004308 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4309 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004310 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004311 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004312 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4313 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004314
4315 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004317 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004321 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004322 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4323 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004326 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004327 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4328 AINPUT_SOURCE_MOUSE)
4329 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4330 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004331 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004332 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004333 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004334
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004336 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004337 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4338 AINPUT_SOURCE_MOUSE)
4339 .buttonState(0)
4340 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004342 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004343 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004346 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004347 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4348 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004349 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004350 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004351 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004352
4353 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004355 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004356 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4357 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004358 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004359 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004360 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004361
4362 // No more events
4363 windowLeft->assertNoEvents();
4364 windowRight->assertNoEvents();
4365}
4366
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004367/**
4368 * Put two fingers down (and don't release them) and click the mouse button.
4369 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4370 * currently active gesture should be canceled, and the new one should proceed.
4371 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004372TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4373 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004375 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4376 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004377 window->setFrame(Rect(0, 0, 600, 800));
4378
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004380
4381 const int32_t touchDeviceId = 4;
4382 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004383
4384 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4386 .deviceId(touchDeviceId)
4387 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4388 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004389
Prabir Pradhan678438e2023-04-13 19:32:51 +00004390 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4391 .deviceId(touchDeviceId)
4392 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4393 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4394 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004395 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4396 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4397
4398 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4400 .deviceId(mouseDeviceId)
4401 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4402 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4403 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004404 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4405 WithPointerCount(2u)));
4406 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4407
Prabir Pradhan678438e2023-04-13 19:32:51 +00004408 mDispatcher->notifyMotion(
4409 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4410 .deviceId(mouseDeviceId)
4411 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4412 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4414 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004415 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4416
4417 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4418 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4420 .deviceId(touchDeviceId)
4421 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4422 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4423 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004424 window->assertNoEvents();
4425}
4426
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004427/**
4428 * Put two fingers down (and don't release them) and click the mouse button.
4429 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4430 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4431 */
4432TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4433 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004435 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4436 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004437 window->setFrame(Rect(0, 0, 600, 800));
4438
4439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4440
4441 const int32_t touchDeviceId = 4;
4442 const int32_t mouseDeviceId = 6;
4443
4444 // Two pointers down
4445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4446 .deviceId(touchDeviceId)
4447 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4448 .build());
4449
4450 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4451 .deviceId(touchDeviceId)
4452 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4453 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4454 .build());
4455 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4456 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4457
4458 // Send a series of mouse events for a mouse click
4459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4460 .deviceId(mouseDeviceId)
4461 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4462 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4463 .build());
4464 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4465
4466 mDispatcher->notifyMotion(
4467 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4468 .deviceId(mouseDeviceId)
4469 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4470 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4472 .build());
4473 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4474
4475 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4476 // already active gesture, it should be sent normally.
4477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4478 .deviceId(touchDeviceId)
4479 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4480 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4481 .build());
4482 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4483 window->assertNoEvents();
4484}
4485
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004486TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4487 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4488
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004489 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4490 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004491 spyWindow->setFrame(Rect(0, 0, 600, 800));
4492 spyWindow->setTrustedOverlay(true);
4493 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004494 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4495 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004496 window->setFrame(Rect(0, 0, 600, 800));
4497
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004498 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004499 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004500
4501 // Send mouse cursor to the window
4502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004503 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004504 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4505 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004506 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004507 .build()));
4508
4509 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4510 WithSource(AINPUT_SOURCE_MOUSE)));
4511 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4512 WithSource(AINPUT_SOURCE_MOUSE)));
4513
4514 window->assertNoEvents();
4515 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004516}
4517
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004518TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4519 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4521
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004522 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4523 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004524 spyWindow->setFrame(Rect(0, 0, 600, 800));
4525 spyWindow->setTrustedOverlay(true);
4526 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4528 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004529 window->setFrame(Rect(0, 0, 600, 800));
4530
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004531 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004532 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004533
4534 // Send mouse cursor to the window
4535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004536 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004537 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4538 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004539 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004540 .build()));
4541
4542 // Move mouse cursor
4543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004544 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004545 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4546 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004547 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004548 .build()));
4549
4550 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4551 WithSource(AINPUT_SOURCE_MOUSE)));
4552 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4553 WithSource(AINPUT_SOURCE_MOUSE)));
4554 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4555 WithSource(AINPUT_SOURCE_MOUSE)));
4556 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4557 WithSource(AINPUT_SOURCE_MOUSE)));
4558 // Touch down on the window
4559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004560 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004561 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4562 AINPUT_SOURCE_TOUCHSCREEN)
4563 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004564 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004565 .build()));
4566 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4567 WithSource(AINPUT_SOURCE_MOUSE)));
4568 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4569 WithSource(AINPUT_SOURCE_MOUSE)));
4570 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4571 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4572 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4573 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4574
4575 // pilfer the motion, retaining the gesture on the spy window.
4576 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4577 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4578 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4579
4580 // Touch UP on the window
4581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004582 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004583 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4584 AINPUT_SOURCE_TOUCHSCREEN)
4585 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004586 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004587 .build()));
4588 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4589 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4590
4591 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4592 // to send a new gesture. It should again go to both windows (spy and the window below), just
4593 // like the first gesture did, before pilfering. The window configuration has not changed.
4594
4595 // One more tap - DOWN
4596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004597 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004598 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4599 AINPUT_SOURCE_TOUCHSCREEN)
4600 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004601 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004602 .build()));
4603 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4604 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4605 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4606 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4607
4608 // Touch UP on the window
4609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004610 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004611 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4612 AINPUT_SOURCE_TOUCHSCREEN)
4613 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004614 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004615 .build()));
4616 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4617 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4618 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4619 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4620
4621 window->assertNoEvents();
4622 spyWindow->assertNoEvents();
4623}
4624
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004625TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4626 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4628
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004629 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4630 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004631 spyWindow->setFrame(Rect(0, 0, 600, 800));
4632 spyWindow->setTrustedOverlay(true);
4633 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004634 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4635 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004636 window->setFrame(Rect(0, 0, 600, 800));
4637
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004638 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004639 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4640
4641 // Send mouse cursor to the window
4642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4643 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4644 .build());
4645
4646 // Move mouse cursor
4647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4648 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4649 .build());
4650
4651 window->consumeMotionEvent(
4652 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4653 spyWindow->consumeMotionEvent(
4654 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4655 window->consumeMotionEvent(
4656 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4657 spyWindow->consumeMotionEvent(
4658 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4659 // Touch down on the window
4660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4661 .deviceId(SECOND_DEVICE_ID)
4662 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4663 .build());
4664 window->consumeMotionEvent(
4665 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4666 spyWindow->consumeMotionEvent(
4667 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4668
4669 // pilfer the motion, retaining the gesture on the spy window.
4670 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4671 window->consumeMotionEvent(
4672 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4673 // Mouse hover is not pilfered
4674
4675 // Touch UP on the window
4676 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4677 .deviceId(SECOND_DEVICE_ID)
4678 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4679 .build());
4680 spyWindow->consumeMotionEvent(
4681 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4682
4683 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4684 // to send a new gesture. It should again go to both windows (spy and the window below), just
4685 // like the first gesture did, before pilfering. The window configuration has not changed.
4686
4687 // One more tap - DOWN
4688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4689 .deviceId(SECOND_DEVICE_ID)
4690 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4691 .build());
4692 window->consumeMotionEvent(
4693 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4694 spyWindow->consumeMotionEvent(
4695 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4696
4697 // Touch UP on the window
4698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4699 .deviceId(SECOND_DEVICE_ID)
4700 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4701 .build());
4702 window->consumeMotionEvent(
4703 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4704 spyWindow->consumeMotionEvent(
4705 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4706
4707 // Mouse movement continues normally as well
4708 // Move mouse cursor
4709 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4710 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4711 .build());
4712 window->consumeMotionEvent(
4713 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4714 spyWindow->consumeMotionEvent(
4715 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4716
4717 window->assertNoEvents();
4718 spyWindow->assertNoEvents();
4719}
4720
Garfield Tandf26e862020-07-01 20:18:19 -07004721// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4722// directly in this test.
4723TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004725 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4726 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004727 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004728
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004729 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004730
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004731 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004732
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004734 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004735 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4736 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004737 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004738 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004739 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004740 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004742 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004743 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4744 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004745 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004746 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004747 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4748 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004749
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004751 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004752 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4753 AINPUT_SOURCE_MOUSE)
4754 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4755 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004756 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004757 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004758 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004759
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004761 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004762 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4763 AINPUT_SOURCE_MOUSE)
4764 .buttonState(0)
4765 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004766 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004767 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004768 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004769
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004771 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004772 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4773 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004774 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004775 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004776 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004777
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004778 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4779 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4780 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004781 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004782 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4783 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004784 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004785 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004786 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004787}
4788
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004789/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004790 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4791 * is generated.
4792 */
4793TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004795 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4796 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004797 window->setFrame(Rect(0, 0, 1200, 800));
4798
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004799 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004800
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004802
4803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004804 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004805 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4806 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004807 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004808 .build()));
4809 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4810
4811 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004812 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004813 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4814}
4815
4816/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004817 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4818 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004819TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4820 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4821 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004823 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4824 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004825 window->setFrame(Rect(0, 0, 1200, 800));
4826
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004827 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004828
4829 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4830
4831 MotionEventBuilder hoverEnterBuilder =
4832 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4833 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4834 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4836 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4838 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4839 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4840 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4841}
4842
4843/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004844 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4845 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004846TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
4847 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004849 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4850 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004851 window->setFrame(Rect(0, 0, 100, 100));
4852
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004853 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004854
4855 const int32_t mouseDeviceId = 7;
4856 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004857
4858 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4860 .deviceId(mouseDeviceId)
4861 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4862 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004863 window->consumeMotionEvent(
4864 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4865
4866 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4868 .deviceId(touchDeviceId)
4869 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4870 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004871
4872 window->consumeMotionEvent(
4873 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4874 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4875}
4876
4877/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004878 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
4879 */
4880TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4881 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004883 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4884 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004885 window->setFrame(Rect(0, 0, 100, 100));
4886
4887 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4888
4889 const int32_t mouseDeviceId = 7;
4890 const int32_t touchDeviceId = 4;
4891
4892 // Start hovering with the mouse
4893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4894 .deviceId(mouseDeviceId)
4895 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4896 .build());
4897 window->consumeMotionEvent(
4898 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4899
4900 // Touch goes down
4901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4902 .deviceId(touchDeviceId)
4903 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4904 .build());
4905 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4906}
4907
4908/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004909 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004910 * The tap causes a HOVER_EXIT event to be generated because the current event
4911 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004912 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004913TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
4914 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004916 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4917 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004918 window->setFrame(Rect(0, 0, 100, 100));
4919
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004920 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4923 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004924 ASSERT_NO_FATAL_FAILURE(
4925 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4926 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004927
4928 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4930 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4931 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004932 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004933 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4934 WithSource(AINPUT_SOURCE_MOUSE))));
4935
4936 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004937 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4938 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4939
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004940 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4941 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4942 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004943 ASSERT_NO_FATAL_FAILURE(
4944 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4945 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4946}
4947
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004948/**
4949 * Send a mouse hover event followed by a tap from touchscreen.
4950 * The tap causes a HOVER_EXIT event to be generated because the current event
4951 * stream's source has been switched.
4952 */
4953TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4954 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004956 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4957 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004958 window->setFrame(Rect(0, 0, 100, 100));
4959
4960 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4961 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4963 .build());
4964
4965 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4966 WithSource(AINPUT_SOURCE_MOUSE)));
4967
4968 // Tap on the window
4969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4970 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4971 .build());
4972
4973 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4974 WithSource(AINPUT_SOURCE_MOUSE)));
4975
4976 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4977 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4978
4979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4980 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4981 .build());
4982
4983 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4984 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4985}
4986
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004987TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4989 sp<FakeWindowHandle> windowDefaultDisplay =
4990 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004991 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004992 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4993 sp<FakeWindowHandle> windowSecondDisplay =
4994 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4995 SECOND_DISPLAY_ID);
4996 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4997
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004998 mDispatcher->onWindowInfosChanged(
4999 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005000
5001 // Set cursor position in window in default display and check that hover enter and move
5002 // events are generated.
5003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005004 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005005 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5006 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005007 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005008 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005009 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005010 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005011
5012 // Remove all windows in secondary display and check that no event happens on window in
5013 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005014 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5015
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005016 windowDefaultDisplay->assertNoEvents();
5017
5018 // Move cursor position in window in default display and check that only hover move
5019 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005020 mDispatcher->onWindowInfosChanged(
5021 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005023 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005024 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5025 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005026 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005027 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005028 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005029 windowDefaultDisplay->consumeMotionEvent(
5030 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5031 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005032 windowDefaultDisplay->assertNoEvents();
5033}
5034
Garfield Tan00f511d2019-06-12 16:55:40 -07005035TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005037
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005038 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5039 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005040 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005041 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5042 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005043 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005044
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005045 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005046
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005047 mDispatcher->onWindowInfosChanged(
5048 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005049
5050 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5051 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005053 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005054 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5055 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005056 windowRight->assertNoEvents();
5057}
5058
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005059TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005060 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005061 sp<FakeWindowHandle> window =
5062 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5063 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005064 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005065
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005066 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005067 setFocusedWindow(window);
5068
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005069 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005070
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005071 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005072
5073 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005074 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005075
5076 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5077 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005078 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005079 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005080}
5081
5082TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005084 sp<FakeWindowHandle> window =
5085 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5086 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005087
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005088 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005089
Prabir Pradhan678438e2023-04-13 19:32:51 +00005090 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005091 AINPUT_SOURCE_TOUCHSCREEN,
5092 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005093
5094 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005095 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005096
5097 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5098 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005099 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005100 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005101 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005102}
5103
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005104TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5105 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005106 sp<FakeWindowHandle> window =
5107 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5108 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005110 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005111
5112 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5113 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5114 .build());
5115
5116 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5117
5118 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5119 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5120 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5121
5122 // After the device has been reset, a new hovering stream can be sent to the window
5123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5124 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5125 .build());
5126 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5127}
5128
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005129TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005131 sp<FakeWindowHandle> window =
5132 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5133 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005134 window->setFocusable(true);
5135
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005136 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005137 setFocusedWindow(window);
5138
5139 window->consumeFocusEvent(true);
5140
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005141 const NotifyKeyArgs keyArgs =
5142 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005143 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5144 const nsecs_t injectTime = keyArgs.eventTime;
5145 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005146 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005147 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005148 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005149 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5150 std::chrono::nanoseconds(interceptKeyTimeout).count());
5151}
5152
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005153/**
5154 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5155 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005156TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005158 sp<FakeWindowHandle> window =
5159 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5160 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005161 window->setFocusable(true);
5162
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005163 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005164 setFocusedWindow(window);
5165
5166 window->consumeFocusEvent(true);
5167
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005168 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5169 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005170
5171 // Set a value that's significantly larger than the default consumption timeout. If the
5172 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5173 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005174 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005175 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005176 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005177}
5178
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005179/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005180 * Two windows. First is a regular window. Second does not overlap with the first, and has
5181 * WATCH_OUTSIDE_TOUCH.
5182 * Both windows are owned by the same UID.
5183 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5184 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5185 */
5186TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005188 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5189 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005190 window->setFrame(Rect{0, 0, 100, 100});
5191
5192 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005193 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005194 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005195 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5196 outsideWindow->setWatchOutsideTouch(true);
5197 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005198 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005199
5200 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005201 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005202 AINPUT_SOURCE_TOUCHSCREEN,
5203 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005204 window->consumeMotionDown();
5205 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5206 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5207 outsideWindow->consumeMotionEvent(
5208 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005209
5210 // Ensure outsideWindow doesn't get any more events for the gesture.
5211 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005212 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005213 window->consumeMotionMove();
5214 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005215}
5216
5217/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005218 * Three windows:
5219 * - Left window
5220 * - Right window
5221 * - Outside window(watch for ACTION_OUTSIDE events)
5222 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5223 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5224 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5225 *
5226 * First, device A report a down event landed in the right window, the outside window can receive
5227 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5228 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5229 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5230 * window can receive it, but outside window event can't receive it.
5231 */
5232TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5234 sp<FakeWindowHandle> leftWindow =
5235 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005236 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005237 leftWindow->setFrame(Rect{0, 0, 100, 100});
5238 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5239
5240 sp<FakeWindowHandle> outsideWindow =
5241 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005242 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005243 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5244 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5245 outsideWindow->setWatchOutsideTouch(true);
5246
5247 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5248 std::make_shared<FakeApplicationHandle>();
5249 sp<FakeWindowHandle> rightWindow =
5250 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005251 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005252 rightWindow->setFrame(Rect{100, 0, 200, 100});
5253 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5254
5255 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5256 // when left window or right window is tapped
5257 mDispatcher->onWindowInfosChanged(
5258 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5259 {},
5260 0,
5261 0});
5262
5263 const DeviceId deviceA = 9;
5264 const DeviceId deviceB = 3;
5265
5266 // Tap on right window use device A
5267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5268 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5269 .deviceId(deviceA)
5270 .build());
5271 leftWindow->assertNoEvents();
5272 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5273 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5274 // with zeroed coords.
5275 outsideWindow->consumeMotionEvent(
5276 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5277
5278 // Tap on left window use device B
5279 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5280 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5281 .deviceId(deviceB)
5282 .build());
5283 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5284 rightWindow->assertNoEvents();
5285 // Because new gesture down on the left window that has the same owner with outside Window, the
5286 // outside Window should receive the ACTION_OUTSIDE with coords.
5287 outsideWindow->consumeMotionEvent(
5288 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5289
5290 // Ensure that windows that can only accept outside do not receive remaining gestures
5291 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5292 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5293 .deviceId(deviceA)
5294 .build());
5295 leftWindow->assertNoEvents();
5296 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5297
5298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5299 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5300 .deviceId(deviceB)
5301 .build());
5302 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5303 rightWindow->assertNoEvents();
5304 outsideWindow->assertNoEvents();
5305}
5306
5307/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005308 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5309 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5310 * ACTION_OUTSIDE event is sent per gesture.
5311 */
5312TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5313 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005315 sp<FakeWindowHandle> window =
5316 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5317 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005318 window->setWatchOutsideTouch(true);
5319 window->setFrame(Rect{0, 0, 100, 100});
5320 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005321 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005322 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005323 secondWindow->setFrame(Rect{100, 100, 200, 200});
5324 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005325 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005326 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005327 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005328 mDispatcher->onWindowInfosChanged(
5329 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005330
5331 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005332 mDispatcher->notifyMotion(
5333 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5334 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005335 window->assertNoEvents();
5336 secondWindow->assertNoEvents();
5337
5338 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5339 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005340 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005341 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005342 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005343 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5344 window->consumeMotionEvent(
5345 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005346 secondWindow->consumeMotionDown();
5347 thirdWindow->assertNoEvents();
5348
5349 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5350 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005351 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005352 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5353 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005354 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005355 window->assertNoEvents();
5356 secondWindow->consumeMotionMove();
5357 thirdWindow->consumeMotionDown();
5358}
5359
Prabir Pradhan814fe082022-07-22 20:22:18 +00005360TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005362 sp<FakeWindowHandle> window =
5363 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5364 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005365 window->setFocusable(true);
5366
Patrick Williamsd828f302023-04-28 17:52:08 -05005367 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005368 setFocusedWindow(window);
5369
5370 window->consumeFocusEvent(true);
5371
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005372 const NotifyKeyArgs keyDown =
5373 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5374 const NotifyKeyArgs keyUp =
5375 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005376 mDispatcher->notifyKey(keyDown);
5377 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005378
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005379 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5380 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005381
5382 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005383 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005384
5385 window->consumeFocusEvent(false);
5386
Prabir Pradhan678438e2023-04-13 19:32:51 +00005387 mDispatcher->notifyKey(keyDown);
5388 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005389 window->assertNoEvents();
5390}
5391
Arthur Hung96483742022-11-15 03:30:48 +00005392TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005394 sp<FakeWindowHandle> window =
5395 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5396 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005397 // Ensure window is non-split and have some transform.
5398 window->setPreventSplitting(true);
5399 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005400 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005401
5402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005403 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5404 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005406 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005407
5408 const MotionEvent secondFingerDownEvent =
5409 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005410 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5413 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005414 .build();
5415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005416 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005417 InputEventInjectionSync::WAIT_FOR_RESULT))
5418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5419
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005420 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5421 ASSERT_NE(nullptr, event);
5422 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5423 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5424 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5425 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5426 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005427}
5428
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005429/**
5430 * Two windows: a splittable and a non-splittable.
5431 * The non-splittable window shouldn't receive any "incomplete" gestures.
5432 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5433 * The second pointer should be dropped because the initial window is splittable, so it won't get
5434 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5435 * "incomplete" gestures.
5436 */
5437TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5439 sp<FakeWindowHandle> leftWindow =
5440 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005441 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005442 leftWindow->setPreventSplitting(false);
5443 leftWindow->setFrame(Rect(0, 0, 100, 100));
5444 sp<FakeWindowHandle> rightWindow =
5445 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005446 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005447 rightWindow->setPreventSplitting(true);
5448 rightWindow->setFrame(Rect(100, 100, 200, 200));
5449 mDispatcher->onWindowInfosChanged(
5450 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5451
5452 // Touch down on left, splittable window
5453 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5454 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5455 .build());
5456 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5457
5458 mDispatcher->notifyMotion(
5459 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5460 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5461 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5462 .build());
5463 leftWindow->assertNoEvents();
5464 rightWindow->assertNoEvents();
5465}
5466
Harry Cuttsb166c002023-05-09 13:06:05 +00005467TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005469 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5470 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005471 window->setFrame(Rect(0, 0, 400, 400));
5472 sp<FakeWindowHandle> trustedOverlay =
5473 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005474 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005475 trustedOverlay->setSpy(true);
5476 trustedOverlay->setTrustedOverlay(true);
5477
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005478 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005479
5480 // Start a three-finger touchpad swipe
5481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5482 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5483 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5484 .build());
5485 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5486 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5487 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5488 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5489 .build());
5490 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5491 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5492 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5493 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5494 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5495 .build());
5496
5497 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5498 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5499 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5500
5501 // Move the swipe a bit
5502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5503 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5504 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5505 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5506 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5507 .build());
5508
5509 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5510
5511 // End the swipe
5512 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5513 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5514 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5515 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5516 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5517 .build());
5518 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5519 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5520 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5521 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5522 .build());
5523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5524 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5525 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5526 .build());
5527
5528 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5529 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5530 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5531
5532 window->assertNoEvents();
5533}
5534
5535TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005537 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5538 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005539 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005540 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005541
5542 // Start a three-finger touchpad swipe
5543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5544 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5545 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5546 .build());
5547 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5548 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5549 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5550 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5551 .build());
5552 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5553 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5554 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5555 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5556 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5557 .build());
5558
5559 // Move the swipe a bit
5560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5561 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5562 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5563 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5564 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5565 .build());
5566
5567 // End the swipe
5568 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5569 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5570 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5571 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5572 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5573 .build());
5574 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5575 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5576 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5577 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5578 .build());
5579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5580 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5581 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5582 .build());
5583
5584 window->assertNoEvents();
5585}
5586
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005587/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005588 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5589 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005590 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005591 */
5592TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005594 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5595 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005596 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005597 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005598
5599 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5601 .downTime(baseTime + 10)
5602 .eventTime(baseTime + 10)
5603 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5604 .build());
5605
5606 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5607
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005608 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005609 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005610
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005612
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005613 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5614 .downTime(baseTime + 10)
5615 .eventTime(baseTime + 30)
5616 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5617 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5618 .build());
5619
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005620 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5621
5622 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005623 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5624 .downTime(baseTime + 10)
5625 .eventTime(baseTime + 40)
5626 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5627 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5628 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005629
5630 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5631
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5633 .downTime(baseTime + 10)
5634 .eventTime(baseTime + 50)
5635 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5636 .build());
5637
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005638 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5639
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5641 .downTime(baseTime + 60)
5642 .eventTime(baseTime + 60)
5643 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5644 .build());
5645
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005646 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005647}
5648
5649/**
Hu Guo771a7692023-09-17 20:51:08 +08005650 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5651 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5652 * its coordinates should be converted by the transform of the windows of target screen.
5653 */
5654TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5655 // This case will create a window and a spy window on the default display and mirror
5656 // window on the second display. cancel event is sent through spy window pilferPointers
5657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5658
5659 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005660 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5661 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005662 spyWindowDefaultDisplay->setTrustedOverlay(true);
5663 spyWindowDefaultDisplay->setSpy(true);
5664
5665 sp<FakeWindowHandle> windowDefaultDisplay =
5666 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005667 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005668 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5669
5670 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5671 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5672
5673 // Add the windows to the dispatcher
5674 mDispatcher->onWindowInfosChanged(
5675 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5676 *windowSecondDisplay->getInfo()},
5677 {},
5678 0,
5679 0});
5680
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005681 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005683 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5684 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5686
5687 spyWindowDefaultDisplay->consumeMotionDown();
5688 windowDefaultDisplay->consumeMotionDown();
5689
5690 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5691
5692 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005693 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5694 ASSERT_NE(nullptr, event);
5695 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005696
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005697 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5698 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5699 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5700 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005701 EXPECT_EQ(100, event->getX(0));
5702 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005703}
5704
5705/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005706 * Ensure the correct coordinate spaces are used by InputDispatcher.
5707 *
5708 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5709 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5710 * space.
5711 */
5712class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5713public:
5714 void SetUp() override {
5715 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005716 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005717 }
5718
Linnan Li13bf76a2024-05-05 19:18:02 +08005719 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005720 gui::DisplayInfo info;
5721 info.displayId = displayId;
5722 info.transform = transform;
5723 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005724 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005725 }
5726
5727 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5728 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005729 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005730 }
5731
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005732 void removeAllWindowsAndDisplays() {
5733 mDisplayInfos.clear();
5734 mWindowInfos.clear();
5735 }
5736
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005737 // Set up a test scenario where the display has a scaled projection and there are two windows
5738 // on the display.
5739 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5740 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5741 // respectively.
5742 ui::Transform displayTransform;
5743 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005744 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005745
5746 std::shared_ptr<FakeApplicationHandle> application =
5747 std::make_shared<FakeApplicationHandle>();
5748
5749 // Add two windows to the display. Their frames are represented in the display space.
5750 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005751 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005752 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005753 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5754 addWindow(firstWindow);
5755
5756 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005757 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005758 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005759 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5760 addWindow(secondWindow);
5761 return {std::move(firstWindow), std::move(secondWindow)};
5762 }
5763
5764private:
5765 std::vector<gui::DisplayInfo> mDisplayInfos;
5766 std::vector<gui::WindowInfo> mWindowInfos;
5767};
5768
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005769TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005770 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5771 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005772 // selected so that if the hit test was performed with the point and the bounds being in
5773 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005774 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005775 AINPUT_SOURCE_TOUCHSCREEN,
5776 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005777
5778 firstWindow->consumeMotionDown();
5779 secondWindow->assertNoEvents();
5780}
5781
5782// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5783// the event should be treated as being in the logical display space.
5784TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5785 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5786 // Send down to the first window. The point is represented in the logical display space. The
5787 // point is selected so that if the hit test was done in logical display space, then it would
5788 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005790 PointF{75 * 2, 55 * 4});
5791
5792 firstWindow->consumeMotionDown();
5793 secondWindow->assertNoEvents();
5794}
5795
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005796// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5797// event should be treated as being in the logical display space.
5798TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5799 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5800
5801 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5802 ui::Transform injectedEventTransform;
5803 injectedEventTransform.set(matrix);
5804 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5805 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5806
5807 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005808 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005809 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005810 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005811 .x(untransformedPoint.x)
5812 .y(untransformedPoint.y))
5813 .build();
5814 event.transform(matrix);
5815
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005816 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005817 InputEventInjectionSync::WAIT_FOR_RESULT);
5818
5819 firstWindow->consumeMotionDown();
5820 secondWindow->assertNoEvents();
5821}
5822
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005823TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5824 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5825
5826 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005827 mDispatcher->notifyMotion(
5828 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5829 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005830
5831 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005832 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5833 ASSERT_NE(nullptr, event);
5834 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005835
5836 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005837 EXPECT_EQ(300, event->getRawX(0));
5838 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005839
5840 // Ensure that the x and y values are in the window's coordinate space.
5841 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5842 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005843 EXPECT_EQ(100, event->getX(0));
5844 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005845}
5846
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005847TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5848 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5849 // The monitor will always receive events in the logical display's coordinate space, because
5850 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005851 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005852
5853 // Send down to the first window.
5854 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005855 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005856 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5857 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5858
5859 // Second pointer goes down on second window.
5860 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005861 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005862 {PointF{50, 100}, PointF{150, 220}}));
5863 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5864 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5865 {1, PointF{300, 880}}};
5866 monitor.consumeMotionEvent(
5867 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5868
5869 mDispatcher->cancelCurrentTouch();
5870
5871 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5872 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5873 monitor.consumeMotionEvent(
5874 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5875}
5876
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005877TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5878 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5879
5880 // Send down to the first window.
5881 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005882 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005883 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5884
5885 // The pointer is transferred to the second window, and the second window receives it in the
5886 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005887 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005888 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5889 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5890}
5891
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005892TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5893 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5894
5895 // Send hover move to the second window, and ensure it shows up as hover enter.
5896 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005897 ui::LogicalDisplayId::DEFAULT,
5898 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005899 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5900 WithCoords(100, 80), WithRawCoords(300, 880)));
5901
5902 // Touch down at the same location and ensure a hover exit is synthesized.
5903 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005904 ui::LogicalDisplayId::DEFAULT,
5905 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005906 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5907 WithRawCoords(300, 880)));
5908 secondWindow->consumeMotionEvent(
5909 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5910 secondWindow->assertNoEvents();
5911 firstWindow->assertNoEvents();
5912}
5913
Prabir Pradhan453ae732023-10-13 14:30:14 +00005914// Same as above, but while the window is being mirrored.
5915TEST_F(InputDispatcherDisplayProjectionTest,
5916 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5917 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5918
5919 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5920 ui::Transform secondDisplayTransform;
5921 secondDisplayTransform.set(matrix);
5922 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5923
5924 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5925 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5926 addWindow(secondWindowClone);
5927
5928 // Send hover move to the second window, and ensure it shows up as hover enter.
5929 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005930 ui::LogicalDisplayId::DEFAULT,
5931 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005932 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5933 WithCoords(100, 80), WithRawCoords(300, 880)));
5934
5935 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5936 // display.
5937 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005938 ui::LogicalDisplayId::DEFAULT,
5939 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005940 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5941 WithRawCoords(300, 880)));
5942 secondWindow->consumeMotionEvent(
5943 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5944 secondWindow->assertNoEvents();
5945 firstWindow->assertNoEvents();
5946}
5947
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005948TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5949 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5950
5951 // Send hover enter to second window
5952 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005953 ui::LogicalDisplayId::DEFAULT,
5954 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005955 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5956 WithCoords(100, 80), WithRawCoords(300, 880)));
5957
5958 mDispatcher->cancelCurrentTouch();
5959
5960 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5961 WithRawCoords(300, 880)));
5962 secondWindow->assertNoEvents();
5963 firstWindow->assertNoEvents();
5964}
5965
Prabir Pradhan453ae732023-10-13 14:30:14 +00005966// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005967TEST_F(InputDispatcherDisplayProjectionTest,
5968 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5969 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5970
5971 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5972 ui::Transform secondDisplayTransform;
5973 secondDisplayTransform.set(matrix);
5974 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5975
5976 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5977 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5978 addWindow(secondWindowClone);
5979
5980 // Send hover enter to second window
5981 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005982 ui::LogicalDisplayId::DEFAULT,
5983 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00005984 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5985 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005986 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005987
5988 mDispatcher->cancelCurrentTouch();
5989
5990 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5991 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5992 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005993 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005994 secondWindow->assertNoEvents();
5995 firstWindow->assertNoEvents();
5996}
5997
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005998/** Ensure consistent behavior of InputDispatcher in all orientations. */
5999class InputDispatcherDisplayOrientationFixture
6000 : public InputDispatcherDisplayProjectionTest,
6001 public ::testing::WithParamInterface<ui::Rotation> {};
6002
6003// This test verifies the touchable region of a window for all rotations of the display by tapping
6004// in different locations on the display, specifically points close to the four corners of a
6005// window.
6006TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6007 constexpr static int32_t displayWidth = 400;
6008 constexpr static int32_t displayHeight = 800;
6009
6010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6011
6012 const auto rotation = GetParam();
6013
6014 // Set up the display with the specified rotation.
6015 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6016 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6017 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6018 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6019 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006020 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006021
6022 // Create a window with its bounds determined in the logical display.
6023 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6024 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006025 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6026 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006027 window->setFrame(frameInDisplay, displayTransform);
6028 addWindow(window);
6029
6030 // The following points in logical display space should be inside the window.
6031 static const std::array<vec2, 4> insidePoints{
6032 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6033 for (const auto pointInsideWindow : insidePoints) {
6034 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6035 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006036 mDispatcher->notifyMotion(
6037 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6038 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006039 window->consumeMotionDown();
6040
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006041 mDispatcher->notifyMotion(
6042 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6043 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006044 window->consumeMotionUp();
6045 }
6046
6047 // The following points in logical display space should be outside the window.
6048 static const std::array<vec2, 5> outsidePoints{
6049 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6050 for (const auto pointOutsideWindow : outsidePoints) {
6051 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6052 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006053 mDispatcher->notifyMotion(
6054 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6055 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006056
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006057 mDispatcher->notifyMotion(
6058 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6059 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006060 }
6061 window->assertNoEvents();
6062}
6063
Linnan Li5e5645e2024-03-05 14:43:05 +00006064// This test verifies the occlusion detection for all rotations of the display by tapping
6065// in different locations on the display, specifically points close to the four corners of a
6066// window.
6067TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6068 constexpr static int32_t displayWidth = 400;
6069 constexpr static int32_t displayHeight = 800;
6070
6071 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6072 std::make_shared<FakeApplicationHandle>();
6073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6074
6075 const auto rotation = GetParam();
6076
6077 // Set up the display with the specified rotation.
6078 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6079 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6080 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6081 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6082 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006083 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006084
6085 // Create a window that not trusted.
6086 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6087
6088 const Rect untrustedWindowFrameInDisplay =
6089 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6090
6091 sp<FakeWindowHandle> untrustedWindow =
6092 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006093 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006094 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6095 untrustedWindow->setTrustedOverlay(false);
6096 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6097 untrustedWindow->setTouchable(false);
6098 untrustedWindow->setAlpha(1.0f);
6099 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6100 addWindow(untrustedWindow);
6101
6102 // Create a simple app window below the untrusted window.
6103 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6104 const Rect simpleAppWindowFrameInDisplay =
6105 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6106
6107 sp<FakeWindowHandle> simpleAppWindow =
6108 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006109 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006110 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6111 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6112 addWindow(simpleAppWindow);
6113
6114 // The following points in logical display space should be inside the untrusted window, so
6115 // the simple window could not receive events that coordinate is these point.
6116 static const std::array<vec2, 4> untrustedPoints{
6117 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6118
6119 for (const auto untrustedPoint : untrustedPoints) {
6120 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6121 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006122 mDispatcher->notifyMotion(
6123 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6124 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6125 mDispatcher->notifyMotion(
6126 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6127 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006128 }
6129 untrustedWindow->assertNoEvents();
6130 simpleAppWindow->assertNoEvents();
6131 // The following points in logical display space should be outside the untrusted window, so
6132 // the simple window should receive events that coordinate is these point.
6133 static const std::array<vec2, 5> trustedPoints{
6134 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6135 for (const auto trustedPoint : trustedPoints) {
6136 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6137 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006138 mDispatcher->notifyMotion(
6139 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6140 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6141 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006142 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006143 mDispatcher->notifyMotion(
6144 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6145 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6146 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006147 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6148 }
6149 untrustedWindow->assertNoEvents();
6150}
6151
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006152// Run the precision tests for all rotations.
6153INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6154 InputDispatcherDisplayOrientationFixture,
6155 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6156 ui::ROTATION_270),
6157 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6158 return ftl::enum_string(testParamInfo.param);
6159 });
6160
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006161using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6162 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006163
6164class TransferTouchFixture : public InputDispatcherTest,
6165 public ::testing::WithParamInterface<TransferFunction> {};
6166
6167TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006169
6170 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006171 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006172 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006173 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006174 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006175 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006176 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006177 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006178 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006179 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6180 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006181 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006182 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006183 mDispatcher->onWindowInfosChanged(
6184 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006185 setFocusedWindow(firstWindow);
6186 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006187
6188 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006190 AINPUT_SOURCE_TOUCHSCREEN,
6191 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006192
Svet Ganov5d3bc372020-01-26 23:11:07 -08006193 // Only the first window should get the down event
6194 firstWindow->consumeMotionDown();
6195 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006196 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006197 // Dispatcher reports pointer down outside focus for the wallpaper
6198 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006199
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006200 // Transfer touch to the second window
6201 TransferFunction f = GetParam();
6202 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6203 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006204 // The first window gets cancel and the second gets down
6205 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006206 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6207 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6208 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006209 // There should not be any changes to the focused window when transferring touch
6210 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006211
6212 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006213 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006214 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006215 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006216 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006217 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6218 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006219 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006220}
6221
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006222/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006223 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6224 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6225 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006226 * natural to the user.
6227 * In this test, we are sending a pointer to both spy window and first window. We then try to
6228 * transfer touch to the second window. The dispatcher should identify the first window as the
6229 * one that should lose the gesture, and therefore the action should be to move the gesture from
6230 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006231 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6232 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006233 */
6234TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6236
6237 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006238 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6239 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006240 spyWindow->setTrustedOverlay(true);
6241 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006242 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6243 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006244 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006245 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6246 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006247
6248 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006249 mDispatcher->onWindowInfosChanged(
6250 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006251
6252 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006253 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006254 AINPUT_SOURCE_TOUCHSCREEN,
6255 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006256 // Only the first window and spy should get the down event
6257 spyWindow->consumeMotionDown();
6258 firstWindow->consumeMotionDown();
6259
6260 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006261 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006262 TransferFunction f = GetParam();
6263 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6264 ASSERT_TRUE(success);
6265 // The first window gets cancel and the second gets down
6266 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006267 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6268 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006269
6270 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006271 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006272 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006273 // The first window gets no events and the second+spy get up
6274 firstWindow->assertNoEvents();
6275 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006276 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6277 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006278}
6279
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006280TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006282
6283 PointF touchPoint = {10, 10};
6284
6285 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006286 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006287 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006288 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006289 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006290 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006291 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006292 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006293 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006294
6295 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006296 mDispatcher->onWindowInfosChanged(
6297 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006298
6299 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006300 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006301 AINPUT_SOURCE_TOUCHSCREEN,
6302 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006303 // Only the first window should get the down event
6304 firstWindow->consumeMotionDown();
6305 secondWindow->assertNoEvents();
6306
6307 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006308 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006309 ui::LogicalDisplayId::DEFAULT,
6310 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006311 // Only the first window should get the pointer down event
6312 firstWindow->consumeMotionPointerDown(1);
6313 secondWindow->assertNoEvents();
6314
6315 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006316 TransferFunction f = GetParam();
6317 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6318 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006319 // The first window gets cancel and the second gets down and pointer down
6320 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006321 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6322 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6323 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006324 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006325
6326 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006327 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006328 ui::LogicalDisplayId::DEFAULT,
6329 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006330 // The first window gets nothing and the second gets pointer up
6331 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006332 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6333 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6334 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6335 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006336
6337 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006338 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006339 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006340 // The first window gets nothing and the second gets up
6341 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006342 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6343 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006344}
6345
Arthur Hungc539dbb2022-12-08 07:45:36 +00006346TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6347 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6348
6349 // Create a couple of windows
6350 sp<FakeWindowHandle> firstWindow =
6351 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006352 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006353 firstWindow->setDupTouchToWallpaper(true);
6354 sp<FakeWindowHandle> secondWindow =
6355 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006356 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006357 secondWindow->setDupTouchToWallpaper(true);
6358
6359 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006360 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6361 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006362 wallpaper1->setIsWallpaper(true);
6363
6364 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006365 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6366 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006367 wallpaper2->setIsWallpaper(true);
6368 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006369 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6370 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6371 {},
6372 0,
6373 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006374
6375 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006376 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006377 AINPUT_SOURCE_TOUCHSCREEN,
6378 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006379
6380 // Only the first window should get the down event
6381 firstWindow->consumeMotionDown();
6382 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006383 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006384 wallpaper2->assertNoEvents();
6385
6386 // Transfer touch focus to the second window
6387 TransferFunction f = GetParam();
6388 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6389 ASSERT_TRUE(success);
6390
6391 // The first window gets cancel and the second gets down
6392 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006393 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6394 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6395 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6396 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006397 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006398
6399 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006400 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006401 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006402 // The first window gets no events and the second gets up
6403 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006404 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6405 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006406 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006407 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006408 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006409}
6410
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006411// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006412// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006413// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006414INSTANTIATE_TEST_SUITE_P(
6415 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6416 ::testing::Values(
6417 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6418 sp<IBinder> destChannelToken) {
6419 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006420 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006421 },
6422 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6423 sp<IBinder> to) {
6424 return dispatcher->transferTouchGesture(from, to,
6425 /*isDragAndDrop=*/false);
6426 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006427
Prabir Pradhan367f3432024-02-13 23:05:58 +00006428TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006430
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006431 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006432 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006433 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006434 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006435
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006436 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006437 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006438 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006439 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006440
6441 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006442 mDispatcher->onWindowInfosChanged(
6443 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006444
6445 PointF pointInFirst = {300, 200};
6446 PointF pointInSecond = {300, 600};
6447
6448 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006449 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006450 AINPUT_SOURCE_TOUCHSCREEN,
6451 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006452 // Only the first window should get the down event
6453 firstWindow->consumeMotionDown();
6454 secondWindow->assertNoEvents();
6455
6456 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006457 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006458 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006459 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006460 // The first window gets a move and the second a down
6461 firstWindow->consumeMotionMove();
6462 secondWindow->consumeMotionDown();
6463
Prabir Pradhan367f3432024-02-13 23:05:58 +00006464 // Transfer touch to the second window
6465 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006466 // The first window gets cancel and the new gets pointer down (it already saw down)
6467 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006468 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006469 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006470
6471 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006472 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006473 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006474 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006475 // The first window gets nothing and the second gets pointer up
6476 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006477 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6478 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6479 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6480 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006481
6482 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006483 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006484 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006485 // The first window gets nothing and the second gets up
6486 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006487 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6488 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006489}
6490
Prabir Pradhan367f3432024-02-13 23:05:58 +00006491// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6492// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6493// receiving touch is not supported, so the touch should continue on those windows and the
6494// transferred-to window should get nothing.
6495TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006496 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6497
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006498 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006499 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006500 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006501 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006502
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006503 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006504 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006505 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006506 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006507
6508 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006509 mDispatcher->onWindowInfosChanged(
6510 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006511
6512 PointF pointInFirst = {300, 200};
6513 PointF pointInSecond = {300, 600};
6514
6515 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006516 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006517 AINPUT_SOURCE_TOUCHSCREEN,
6518 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006519 // Only the first window should get the down event
6520 firstWindow->consumeMotionDown();
6521 secondWindow->assertNoEvents();
6522
6523 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006524 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006525 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006526 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006527 // The first window gets a move and the second a down
6528 firstWindow->consumeMotionMove();
6529 secondWindow->consumeMotionDown();
6530
6531 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006532 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6533 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006534 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006535 ASSERT_FALSE(transferred);
6536 firstWindow->assertNoEvents();
6537 secondWindow->assertNoEvents();
6538
6539 // The rest of the dispatch should proceed as normal
6540 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006541 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006542 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006543 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006544 // The first window gets MOVE and the second gets pointer up
6545 firstWindow->consumeMotionMove();
6546 secondWindow->consumeMotionUp();
6547
6548 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006549 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006550 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006551 // The first window gets nothing and the second gets up
6552 firstWindow->consumeMotionUp();
6553 secondWindow->assertNoEvents();
6554}
6555
Arthur Hungabbb9d82021-09-01 14:52:30 +00006556// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006557// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006558// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006559TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6561 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006562 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6563 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006564 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006565 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006566 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6567 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006568 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006569
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006570 sp<FakeWindowHandle> mirrorWindowInPrimary =
6571 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006572 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006573
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006574 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006575 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006576
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006577 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006578 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006579
6580 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006581 mDispatcher->onWindowInfosChanged(
6582 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6583 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6584 *secondWindowInPrimary->getInfo()},
6585 {},
6586 0,
6587 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006588
6589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006590 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6591 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006592 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6593
6594 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006595 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006596
Prabir Pradhan367f3432024-02-13 23:05:58 +00006597 // Transfer touch
6598 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6599 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006600 // The first window gets cancel.
6601 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006602 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006603 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006604
6605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006606 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006607 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006608 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6609 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006610 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006611 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006612
6613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006614 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006615 {150, 50}))
6616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6617 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006618 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6619 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006620}
6621
Prabir Pradhan367f3432024-02-13 23:05:58 +00006622// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6623// 'transferTouchOnDisplay' api.
6624TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6626 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006627 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6628 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006629 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006630 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006631 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6632 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006633 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006634
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006635 sp<FakeWindowHandle> mirrorWindowInPrimary =
6636 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006637 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006638
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006639 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006640 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006641
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006642 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006643 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006644
6645 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006646 mDispatcher->onWindowInfosChanged(
6647 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6648 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6649 *secondWindowInPrimary->getInfo()},
6650 {},
6651 0,
6652 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006653
6654 // Touch on second display.
6655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006656 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6657 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6659
6660 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006661 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006662
6663 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006664 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6665 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006666
6667 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006668 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006669 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6670 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006671
6672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006673 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006674 SECOND_DISPLAY_ID, {150, 50}))
6675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006676 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006677 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6678 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006679
6680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006681 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006683 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006684 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006685}
6686
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006687TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006689 sp<FakeWindowHandle> window =
6690 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6691 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006692
Vishnu Nair47074b82020-08-14 11:54:47 -07006693 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006694 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006695 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006696
6697 window->consumeFocusEvent(true);
6698
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006699 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006700
6701 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006702 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006703
6704 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006705 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006706 mFakePolicy->assertUserActivityPoked();
6707}
6708
6709TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006711 sp<FakeWindowHandle> window =
6712 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6713 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006714
6715 window->setDisableUserActivity(true);
6716 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006718 setFocusedWindow(window);
6719
6720 window->consumeFocusEvent(true);
6721
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006722 mDispatcher->notifyKey(
6723 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006724
6725 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006726 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006727
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006728 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006729 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006730 mFakePolicy->assertUserActivityNotPoked();
6731}
6732
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006733TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00006734 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006735 sp<FakeWindowHandle> window =
6736 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6737 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006738
6739 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006740 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006741 setFocusedWindow(window);
6742
6743 window->consumeFocusEvent(true);
6744
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006745 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6746
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006747 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006748 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006749 mDispatcher->waitForIdle();
6750
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006751 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00006752 window->assertNoEvents();
6753
6754 // Should have poked user activity
6755 mFakePolicy->assertUserActivityPoked();
6756}
6757
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006758TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00006759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006760 sp<FakeWindowHandle> window =
6761 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6762 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006763
6764 window->setDisableUserActivity(true);
6765 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006767 setFocusedWindow(window);
6768
6769 window->consumeFocusEvent(true);
6770
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006771 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6772
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006773 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006774 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006775 mDispatcher->waitForIdle();
6776
6777 // System key is not passed down
6778 window->assertNoEvents();
6779
6780 // Should have poked user activity
6781 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006782}
6783
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006784class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
6785 public ::testing::WithParamInterface<bool> {};
6786
6787TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
6788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6789 sp<FakeWindowHandle> window =
6790 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6791 ui::LogicalDisplayId::DEFAULT);
6792
6793 window->setDisableUserActivity(GetParam());
6794
6795 window->setFocusable(true);
6796 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6797 setFocusedWindow(window);
6798
6799 window->consumeFocusEvent(true);
6800
6801 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
6802 .keyCode(AKEYCODE_A)
6803 .policyFlags(0)
6804 .build());
6805 mDispatcher->waitForIdle();
6806
6807 // Key is not passed down
6808 window->assertNoEvents();
6809
6810 // Should not have poked user activity
6811 mFakePolicy->assertUserActivityNotPoked();
6812}
6813
6814INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
6815 ::testing::Bool());
6816
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006817TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006819 sp<FakeWindowHandle> window =
6820 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6821 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006822
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006824
6825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006826 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006827 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6829
6830 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006831 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006832
6833 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006834 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006835 mFakePolicy->assertUserActivityPoked();
6836}
6837
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006838TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006840 sp<FakeWindowHandle> window =
6841 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6842 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006843
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006844 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006845
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006846 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006847 mDispatcher->waitForIdle();
6848
6849 window->assertNoEvents();
6850}
6851
6852// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6853TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006855 sp<FakeWindowHandle> window =
6856 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6857 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006858
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006859 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006860
6861 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006862 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006863 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006864 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006865 AINPUT_SOURCE_TOUCHSCREEN,
6866 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006867
6868 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006869 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006870 window->assertNoEvents(); // Key event or focus event will not be received
6871}
6872
arthurhungea3f4fc2020-12-21 23:18:53 +08006873TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6875
arthurhungea3f4fc2020-12-21 23:18:53 +08006876 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006877 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006878 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006879 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006880
arthurhungea3f4fc2020-12-21 23:18:53 +08006881 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006882 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006883 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006884 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006885
6886 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006887 mDispatcher->onWindowInfosChanged(
6888 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006889
6890 PointF pointInFirst = {300, 200};
6891 PointF pointInSecond = {300, 600};
6892
6893 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006894 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006895 AINPUT_SOURCE_TOUCHSCREEN,
6896 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006897 // Only the first window should get the down event
6898 firstWindow->consumeMotionDown();
6899 secondWindow->assertNoEvents();
6900
6901 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006902 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006903 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006904 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006905 // The first window gets a move and the second a down
6906 firstWindow->consumeMotionMove();
6907 secondWindow->consumeMotionDown();
6908
6909 // Send pointer cancel to the second window
6910 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006911 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
6912 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08006913 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006914 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006915 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006916 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6917 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08006918
6919 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006920 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006921 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006922 // The first window gets up and the second gets nothing.
6923 firstWindow->consumeMotionUp();
6924 secondWindow->assertNoEvents();
6925}
6926
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006927TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6929
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006930 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6931 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006932 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006933 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6934 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6935 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6936
Harry Cutts33476232023-01-30 19:57:29 +00006937 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006938 window->assertNoEvents();
6939 mDispatcher->waitForIdle();
6940}
6941
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006942using InputDispatcherMonitorTest = InputDispatcherTest;
6943
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006944/**
6945 * Two entities that receive touch: A window, and a global monitor.
6946 * The touch goes to the window, and then the window disappears.
6947 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6948 * for the monitor, as well.
6949 * 1. foregroundWindow
6950 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6951 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006952TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006954 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
6955 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006956
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006957 FakeMonitorReceiver monitor =
6958 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006959
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006960 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006962 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6963 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6965
6966 // Both the foreground window and the global monitor should receive the touch down
6967 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006968 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006969
6970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006971 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006972 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6974
6975 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006976 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006977
6978 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006979 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006980 window->consumeMotionCancel();
6981 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6982
6983 // If more events come in, there will be no more foreground window to send them to. This will
6984 // cause a cancel for the monitor, as well.
6985 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006986 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006987 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006988 << "Injection should fail because the window was removed";
6989 window->assertNoEvents();
6990 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006991 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006992}
6993
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006994TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006995 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006996 sp<FakeWindowHandle> window =
6997 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6998 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006999 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007000
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007001 FakeMonitorReceiver monitor =
7002 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007003
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007005 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7006 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007008 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7009 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007010}
7011
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007012TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007013 FakeMonitorReceiver monitor =
7014 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007015
Chris Yea209fde2020-07-22 13:54:51 -07007016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007017 sp<FakeWindowHandle> window =
7018 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7019 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007020 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007021
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007023 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7024 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007026 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7027 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007028
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007029 // Pilfer pointers from the monitor.
7030 // This should not do anything and the window should continue to receive events.
7031 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007034 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007035 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007037
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007038 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7039 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007040}
7041
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007042TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007044 sp<FakeWindowHandle> window =
7045 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7046 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007047 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007048 window->setWindowOffset(20, 40);
7049 window->setWindowTransform(0, 1, -1, 0);
7050
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007051 FakeMonitorReceiver monitor =
7052 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007053
7054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7056 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007058 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007059 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7060 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007061 // Even though window has transform, gesture monitor must not.
7062 ASSERT_EQ(ui::Transform(), event->getTransform());
7063}
7064
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007065TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007067 FakeMonitorReceiver monitor =
7068 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007069
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007070 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007071 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7072 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007073 << "Injection should fail if there is a monitor, but no touchable window";
7074 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007075}
7076
Linnan Lid8150952024-01-26 18:07:17 +00007077/**
7078 * Two displays
7079 * The first monitor has a foreground window, a monitor
7080 * The second window has only one monitor.
7081 * We first inject a Down event into the first display, this injection should succeed and both
7082 * the foreground window and monitor should receive a down event, then inject a Down event into
7083 * the second display as well, this injection should fail, at this point, the first display
7084 * window and monitor should not receive a cancel or any other event.
7085 * Continue to inject Move and UP events to the first display, the events should be received
7086 * normally by the foreground window and monitor.
7087 */
7088TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007090 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7091 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007092
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007093 FakeMonitorReceiver monitor =
7094 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007095 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7096
7097 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007099 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7100 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007101 << "The down event injected into the first display should succeed";
7102
7103 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007104 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007105
7106 ASSERT_EQ(InputEventInjectionResult::FAILED,
7107 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7108 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007109 << "The down event injected into the second display should fail since there's no "
7110 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007111
7112 // Continue to inject event to first display.
7113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7114 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007115 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007116 << "The move event injected into the first display should succeed";
7117
7118 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007119 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007120
7121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007122 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007123 {110, 220}))
7124 << "The up event injected into the first display should succeed";
7125
7126 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007127 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007128
7129 window->assertNoEvents();
7130 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007131 secondMonitor.assertNoEvents();
7132}
7133
7134/**
7135 * Two displays
7136 * There is a monitor and foreground window on each display.
7137 * First, we inject down events into each of the two displays, at this point, the foreground windows
7138 * and monitors on both displays should receive down events.
7139 * At this point, the foreground window of the second display goes away, the gone window should
7140 * receive the cancel event, and the other windows and monitors should not receive any events.
7141 * Inject a move event into the second display. At this point, the injection should fail because
7142 * the second display no longer has a foreground window. At this point, the monitor on the second
7143 * display should receive a cancel event, and any windows or monitors on the first display should
7144 * not receive any events, and any subsequent injection of events into the second display should
7145 * also fail.
7146 * Continue to inject events into the first display, and the events should all be injected
7147 * successfully and received normally.
7148 */
7149TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007151 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7152 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007153 sp<FakeWindowHandle> secondWindow =
7154 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7155 SECOND_DISPLAY_ID);
7156
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007157 FakeMonitorReceiver monitor =
7158 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007159 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7160
7161 // There is a foreground window on both displays.
7162 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007164 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7165 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007166 << "The down event injected into the first display should succeed";
7167
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007168 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7169 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007170
7171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7172 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7173 {100, 200}))
7174 << "The down event injected into the second display should succeed";
7175
Linnan Lid8150952024-01-26 18:07:17 +00007176 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7177 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7178
7179 // Now second window is gone away.
7180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7181
7182 // The gone window should receive a cancel, and the monitor on the second display should not
7183 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007184 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7185 secondMonitor.assertNoEvents();
7186
7187 ASSERT_EQ(InputEventInjectionResult::FAILED,
7188 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7189 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007190 << "The move event injected into the second display should fail because there's no "
7191 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007192 // Now the monitor on the second display should receive a cancel event.
7193 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007194
7195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7196 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007197 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007198 << "The move event injected into the first display should succeed";
7199
7200 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007201 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007202
7203 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007204 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7205 {110, 220}))
7206 << "The up event injected into the second display should fail because there's no "
7207 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007208
7209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007210 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007211 {110, 220}))
7212 << "The up event injected into the first display should succeed";
7213
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007214 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7215 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007216
Linnan Lid8150952024-01-26 18:07:17 +00007217 window->assertNoEvents();
7218 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007219 secondWindow->assertNoEvents();
7220 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007221}
7222
7223/**
7224 * One display with transform
7225 * There is a foreground window and a monitor on the display
7226 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7227 * event and move event, then let the foreground window go away, the foreground window receives
7228 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7229 * by the monitor should be with the same transform as the display
7230 */
7231TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007233 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7234 ui::LogicalDisplayId::DEFAULT);
7235 FakeMonitorReceiver monitor =
7236 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007237
7238 ui::Transform transform;
7239 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7240
7241 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007242 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007243 displayInfo.transform = transform;
7244
7245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7246
7247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007248 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7249 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007250 << "The down event injected should succeed";
7251
7252 window->consumeMotionDown();
7253 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7254 EXPECT_EQ(transform, downMotionEvent->getTransform());
7255 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7256
7257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7258 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007259 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007260 << "The move event injected should succeed";
7261
7262 window->consumeMotionMove();
7263 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7264 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7265 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7266
7267 // Let foreground window gone
7268 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7269
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007270 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007271 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007272
7273 ASSERT_EQ(InputEventInjectionResult::FAILED,
7274 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007275 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007276 << "The move event injected should failed";
7277 // Now foreground should not receive any events, but monitor should receive a cancel event
7278 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007279 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7280 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007281 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007282 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7283
7284 // Other event inject to this display should fail.
7285 ASSERT_EQ(InputEventInjectionResult::FAILED,
7286 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007287 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007288 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007289 window->assertNoEvents();
7290 monitor.assertNoEvents();
7291}
7292
chaviw81e2bb92019-12-18 15:03:51 -08007293TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007295 sp<FakeWindowHandle> window =
7296 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7297 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007298
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007299 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007300
7301 NotifyMotionArgs motionArgs =
7302 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007303 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007304
Prabir Pradhan678438e2023-04-13 19:32:51 +00007305 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007306 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007307 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007308
7309 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007310 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007311 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7312 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7313 motionArgs.pointerCoords[0].getX() - 10);
7314
Prabir Pradhan678438e2023-04-13 19:32:51 +00007315 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007316 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007317}
7318
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007319/**
7320 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7321 * the device default right away. In the test scenario, we check both the default value,
7322 * and the action of enabling / disabling.
7323 */
7324TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007326 sp<FakeWindowHandle> window =
7327 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7328 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007329 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007330
7331 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007332 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007333 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007334
7335 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007336 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007337 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007338 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007339
7340 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007341 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007342 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007343 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007344
7345 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007346 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007347 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007348 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007349 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007350 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007351 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007352 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007353
7354 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007355 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007357 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007358
7359 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007360 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007361 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007362 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007363 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007364 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007365 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007366 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007367
7368 window->assertNoEvents();
7369}
7370
Gang Wange9087892020-01-07 12:17:14 -05007371TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007373 sp<FakeWindowHandle> window =
7374 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7375 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007376
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007377 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007378 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007379
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007381 setFocusedWindow(window);
7382
Harry Cutts33476232023-01-30 19:57:29 +00007383 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007384
Prabir Pradhan678438e2023-04-13 19:32:51 +00007385 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7386 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007387
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007388 std::unique_ptr<KeyEvent> event = window->consumeKey();
7389 ASSERT_NE(event, nullptr);
7390 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007391 ASSERT_NE(verified, nullptr);
7392 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7393
7394 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7395 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7396 ASSERT_EQ(keyArgs.source, verified->source);
7397 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7398
7399 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7400
7401 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007402 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007403 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007404 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7405 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7406 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7407 ASSERT_EQ(0, verifiedKey.repeatCount);
7408}
7409
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007410TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007412 sp<FakeWindowHandle> window =
7413 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7414 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007415
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007416 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007417
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007418 ui::Transform transform;
7419 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7420
7421 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007422 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007423 displayInfo.transform = transform;
7424
Patrick Williamsd828f302023-04-28 17:52:08 -05007425 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007426
Prabir Pradhan678438e2023-04-13 19:32:51 +00007427 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007428 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007429 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007430 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007431
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007432 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7433 ASSERT_NE(nullptr, event);
7434 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007435 ASSERT_NE(verified, nullptr);
7436 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7437
7438 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7439 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7440 EXPECT_EQ(motionArgs.source, verified->source);
7441 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7442
7443 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7444
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007445 const vec2 rawXY =
7446 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7447 motionArgs.pointerCoords[0].getXYValue());
7448 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7449 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007450 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007451 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007452 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007453 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7454 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7455}
7456
chaviw09c8d2d2020-08-24 15:48:26 -07007457/**
7458 * Ensure that separate calls to sign the same data are generating the same key.
7459 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7460 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7461 * tests.
7462 */
7463TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7464 KeyEvent event = getTestKeyEvent();
7465 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7466
7467 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7468 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7469 ASSERT_EQ(hmac1, hmac2);
7470}
7471
7472/**
7473 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7474 */
7475TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7476 KeyEvent event = getTestKeyEvent();
7477 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7478 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7479
7480 verifiedEvent.deviceId += 1;
7481 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7482
7483 verifiedEvent.source += 1;
7484 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7485
7486 verifiedEvent.eventTimeNanos += 1;
7487 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7488
Linnan Li13bf76a2024-05-05 19:18:02 +08007489 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007490 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7491
7492 verifiedEvent.action += 1;
7493 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7494
7495 verifiedEvent.downTimeNanos += 1;
7496 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7497
7498 verifiedEvent.flags += 1;
7499 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7500
7501 verifiedEvent.keyCode += 1;
7502 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7503
7504 verifiedEvent.scanCode += 1;
7505 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7506
7507 verifiedEvent.metaState += 1;
7508 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7509
7510 verifiedEvent.repeatCount += 1;
7511 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7512}
7513
Vishnu Nair958da932020-08-21 17:12:37 -07007514TEST_F(InputDispatcherTest, SetFocusedWindow) {
7515 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007516 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7517 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007518 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007519 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7520 ui::LogicalDisplayId::DEFAULT);
7521 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007522
7523 // Top window is also focusable but is not granted focus.
7524 windowTop->setFocusable(true);
7525 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007526 mDispatcher->onWindowInfosChanged(
7527 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007528 setFocusedWindow(windowSecond);
7529
7530 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007532 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007533
7534 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007535 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007536 windowTop->assertNoEvents();
7537}
7538
7539TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007541 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7542 ui::LogicalDisplayId::DEFAULT);
7543 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007544
7545 window->setFocusable(true);
7546 // Release channel for window is no longer valid.
7547 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007548 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007549 setFocusedWindow(window);
7550
7551 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007552 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007553
7554 // window channel is invalid, so it should not receive any input event.
7555 window->assertNoEvents();
7556}
7557
7558TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007560 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7561 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007562 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007563 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007564
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007565 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007566 setFocusedWindow(window);
7567
7568 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007569 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007570
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007571 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007572 window->assertNoEvents();
7573}
7574
7575TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007577 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7578 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007579 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007580 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7581 ui::LogicalDisplayId::DEFAULT);
7582 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007583
7584 windowTop->setFocusable(true);
7585 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007586 mDispatcher->onWindowInfosChanged(
7587 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007588 setFocusedWindow(windowTop);
7589 windowTop->consumeFocusEvent(true);
7590
Chavi Weingarten847e8512023-03-29 00:26:09 +00007591 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007592 mDispatcher->onWindowInfosChanged(
7593 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007594 windowSecond->consumeFocusEvent(true);
7595 windowTop->consumeFocusEvent(false);
7596
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007598 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007599
7600 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007601 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007602}
7603
Chavi Weingarten847e8512023-03-29 00:26:09 +00007604TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007606 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7607 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007608 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007609 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7610 ui::LogicalDisplayId::DEFAULT);
7611 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007612
7613 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007614 windowSecond->setFocusable(false);
7615 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007616 mDispatcher->onWindowInfosChanged(
7617 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007618 setFocusedWindow(windowTop);
7619 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007620
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007622 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007623
7624 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007625 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007626 windowSecond->assertNoEvents();
7627}
7628
7629TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7630 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007631 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7632 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007633 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007634 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007635 ui::LogicalDisplayId::DEFAULT);
7636 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007637
7638 window->setFocusable(true);
7639 previousFocusedWindow->setFocusable(true);
7640 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007641 mDispatcher->onWindowInfosChanged(
7642 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007643 setFocusedWindow(previousFocusedWindow);
7644 previousFocusedWindow->consumeFocusEvent(true);
7645
7646 // Requesting focus on invisible window takes focus from currently focused window.
7647 setFocusedWindow(window);
7648 previousFocusedWindow->consumeFocusEvent(false);
7649
7650 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007652 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007653 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007654
7655 // Window does not get focus event or key down.
7656 window->assertNoEvents();
7657
7658 // Window becomes visible.
7659 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007660 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007661
7662 // Window receives focus event.
7663 window->consumeFocusEvent(true);
7664 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007665 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007666}
7667
Vishnu Nair599f1412021-06-21 10:39:58 -07007668TEST_F(InputDispatcherTest, DisplayRemoved) {
7669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7671 ui::LogicalDisplayId::DEFAULT);
7672 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007673
7674 // window is granted focus.
7675 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007676 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007677 setFocusedWindow(window);
7678 window->consumeFocusEvent(true);
7679
7680 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007681 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007682 window->consumeFocusEvent(false);
7683}
7684
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007685/**
7686 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7687 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7688 * of the 'slipperyEnterWindow'.
7689 *
7690 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7691 * a way so that the touched location is no longer covered by the top window.
7692 *
7693 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7694 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7695 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7696 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7697 * with ACTION_DOWN).
7698 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7699 * window moved itself away from the touched location and had Flag::SLIPPERY.
7700 *
7701 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7702 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7703 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7704 *
7705 * In this test, we ensure that the event received by the bottom window has
7706 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7707 */
7708TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007709 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007710 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007711
7712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007713 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007714
7715 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007716 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7717 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007718 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007719 // Make sure this one overlaps the bottom window
7720 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7721 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7722 // one. Windows with the same owner are not considered to be occluding each other.
7723 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7724
7725 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007726 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7727 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007728 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7729
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007730 mDispatcher->onWindowInfosChanged(
7731 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007732
7733 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007734 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007735 AINPUT_SOURCE_TOUCHSCREEN,
7736 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007737 slipperyExitWindow->consumeMotionDown();
7738 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007739 mDispatcher->onWindowInfosChanged(
7740 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007741
Prabir Pradhan678438e2023-04-13 19:32:51 +00007742 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007743 AINPUT_SOURCE_TOUCHSCREEN,
7744 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007745
7746 slipperyExitWindow->consumeMotionCancel();
7747
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007748 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007749 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7750}
7751
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007752/**
7753 * Two windows, one on the left and another on the right. The left window is slippery. The right
7754 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
7755 * touch moves from the left window into the right window, the gesture should continue to go to the
7756 * left window. Touch shouldn't slip because the right window can't receive touches. This test
7757 * reproduces a crash.
7758 */
7759TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
7760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7761
7762 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007763 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7764 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007765 leftSlipperyWindow->setSlippery(true);
7766 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
7767
7768 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007769 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7770 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007771 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
7772 rightDropTouchesWindow->setDropInput(true);
7773
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007774 mDispatcher->onWindowInfosChanged(
7775 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007776
7777 // Start touch in the left window
7778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7779 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7780 .build());
7781 leftSlipperyWindow->consumeMotionDown();
7782
7783 // And move it into the right window
7784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7785 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7786 .build());
7787
7788 // Since the right window isn't eligible to receive input, touch does not slip.
7789 // The left window continues to receive the gesture.
7790 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7791 rightDropTouchesWindow->assertNoEvents();
7792}
7793
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007794/**
7795 * A single window is on screen first. Touch is injected into that window. Next, a second window
7796 * appears. Since the first window is slippery, touch will move from the first window to the second.
7797 */
7798TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7800 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007801 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
7802 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007803 originalWindow->setFrame(Rect(0, 0, 200, 200));
7804 originalWindow->setSlippery(true);
7805
7806 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007807 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
7808 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007809 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7810
7811 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7812
7813 // Touch down on the original window
7814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7815 injectMotionEvent(*mDispatcher,
7816 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7817 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7818 .build()));
7819 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7820
7821 // Now, a new window appears. This could be, for example, a notification shade that appears
7822 // after user starts to drag down on the launcher window.
7823 mDispatcher->onWindowInfosChanged(
7824 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7826 injectMotionEvent(*mDispatcher,
7827 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7828 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7829 .build()));
7830 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7831 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7833 injectMotionEvent(*mDispatcher,
7834 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7835 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7836 .build()));
7837 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7838
7839 originalWindow->assertNoEvents();
7840 appearingWindow->assertNoEvents();
7841}
7842
Linnan Li49b2b202024-04-12 12:46:40 +08007843/**
7844 * Three windows:
7845 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
7846 * - right window
7847 * - spy window
7848 * The three windows do not overlap.
7849 *
7850 * We have two devices reporting events:
7851 * - Device A reports ACTION_DOWN, which lands in the left window
7852 * - Device B reports ACTION_DOWN, which lands in the spy window.
7853 * - Now, device B reports ACTION_MOVE events which move to the right window.
7854 *
7855 * The right window should not receive any events because the spy window is not a foreground window,
7856 * and also it does not support slippery touches.
7857 */
7858TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
7859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7860 sp<FakeWindowHandle> leftWindow =
7861 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007862 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007863 leftWindow->setFrame(Rect(0, 0, 100, 100));
7864 leftWindow->setSlippery(true);
7865
7866 sp<FakeWindowHandle> rightWindow =
7867 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007868 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007869 rightWindow->setFrame(Rect(100, 0, 200, 100));
7870
7871 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007872 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
7873 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007874 spyWindow->setFrame(Rect(200, 0, 300, 100));
7875 spyWindow->setSpy(true);
7876 spyWindow->setTrustedOverlay(true);
7877
7878 mDispatcher->onWindowInfosChanged(
7879 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
7880
7881 const DeviceId deviceA = 9;
7882 const DeviceId deviceB = 3;
7883
7884 // Tap on left window with device A
7885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7886 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7887 .deviceId(deviceA)
7888 .build());
7889 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7890
7891 // Tap on spy window with device B
7892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7893 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7894 .deviceId(deviceB)
7895 .build());
7896 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7897
7898 // Move to right window with device B. Touches should not slip to the right window, because spy
7899 // window is not a foreground window, and it does not have FLAG_SLIPPERY
7900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7901 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7902 .deviceId(deviceB)
7903 .build());
7904 leftWindow->assertNoEvents();
7905 rightWindow->assertNoEvents();
7906 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7907}
7908
7909/**
7910 * Three windows arranged horizontally and without any overlap.
7911 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
7912 *
7913 * We have two devices reporting events:
7914 * - Device A reports ACTION_DOWN which lands in the left window
7915 * - Device B reports ACTION_DOWN which lands in the right window
7916 * - Device B reports ACTION_MOVE that shifts to the middle window.
7917 * This should cause touches for Device B to slip from the right window to the middle window.
7918 * The right window should receive ACTION_CANCEL for device B and the
7919 * middle window should receive down event for Device B.
7920 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
7921 */
7922TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07007923 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08007924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7925 sp<FakeWindowHandle> leftWindow =
7926 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007927 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007928 leftWindow->setFrame(Rect(0, 0, 100, 100));
7929 leftWindow->setSlippery(true);
7930
7931 sp<FakeWindowHandle> middleWindow =
7932 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007933 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007934 middleWindow->setFrame(Rect(100, 0, 200, 100));
7935
7936 sp<FakeWindowHandle> rightWindow =
7937 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007938 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007939 rightWindow->setFrame(Rect(200, 0, 300, 100));
7940 rightWindow->setSlippery(true);
7941
7942 mDispatcher->onWindowInfosChanged(
7943 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
7944 {},
7945 0,
7946 0});
7947
7948 const DeviceId deviceA = 9;
7949 const DeviceId deviceB = 3;
7950
7951 // Tap on left window with device A
7952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7953 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7954 .deviceId(deviceA)
7955 .build());
7956 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7957
7958 // Tap on right window with device B
7959 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7960 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7961 .deviceId(deviceB)
7962 .build());
7963 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7964
7965 // Move to middle window with device B. Touches should slip to middle window, because right
7966 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
7967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7968 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7969 .deviceId(deviceB)
7970 .build());
7971 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
7972 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7973
7974 // Move to middle window with device A. Touches should slip to middle window, because left
7975 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
7976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7977 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7978 .deviceId(deviceA)
7979 .build());
7980 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
7981 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7982
7983 // Ensure that middle window can receive the remaining move events.
7984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7985 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
7986 .deviceId(deviceB)
7987 .build());
7988 leftWindow->assertNoEvents();
7989 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7990 rightWindow->assertNoEvents();
7991}
7992
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007993TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007994 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007995 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7996
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007997 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7998 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007999 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008000 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008001
8002 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008003 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8004 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008005 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008006 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008007 rightSpy->setSpy(true);
8008 rightSpy->setTrustedOverlay(true);
8009
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008010 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8011 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008012 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008013 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008014
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008015 mDispatcher->onWindowInfosChanged(
8016 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008017
8018 // Touch in the left window
8019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8020 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8021 .build());
8022 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8023 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008024 ASSERT_NO_FATAL_FAILURE(
8025 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008026
8027 // Touch another finger over the right windows
8028 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8029 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8030 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8031 .build());
8032 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8033 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8034 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8035 mDispatcher->waitForIdle();
8036 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008037 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8038 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008039
8040 // Release finger over left window. The UP actions are not treated as device interaction.
8041 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8042 // is part of the UP action, we do not treat this as device interaction.
8043 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8044 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8045 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8046 .build());
8047 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8048 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8049 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8050 mDispatcher->waitForIdle();
8051 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8052
8053 // Move remaining finger
8054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8055 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8056 .build());
8057 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8058 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8059 mDispatcher->waitForIdle();
8060 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008061 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008062
8063 // Release all fingers
8064 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8065 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8066 .build());
8067 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8068 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8069 mDispatcher->waitForIdle();
8070 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8071}
8072
8073TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8075
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008076 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8077 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008078 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008079 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008080
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008081 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008082 setFocusedWindow(window);
8083 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8084
8085 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008086 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008087 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008088 ASSERT_NO_FATAL_FAILURE(
8089 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008090
8091 // The UP actions are not treated as device interaction.
8092 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008093 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008094 mDispatcher->waitForIdle();
8095 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8096}
8097
Prabir Pradhan5893d362023-11-17 04:30:40 +00008098TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8100
8101 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008102 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008103 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008104 sp<FakeWindowHandle> right =
8105 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8106 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008107 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008108 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8109 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008110 spy->setFrame(Rect(0, 0, 200, 100));
8111 spy->setTrustedOverlay(true);
8112 spy->setSpy(true);
8113
8114 mDispatcher->onWindowInfosChanged(
8115 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8116
8117 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008118 NotifyMotionArgs notifyArgs =
8119 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8120 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008121 mDispatcher->notifyMotion(notifyArgs);
8122
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008123 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008124 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8125 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008126 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008127 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8128 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008129 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008130 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8131
8132 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008133 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8134 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008135 mDispatcher->notifyMotion(notifyArgs);
8136
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008137 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008138 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8139 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008140 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008141 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8142 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008143 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008144 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8145
8146 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8147}
8148
Linnan Liccf6ce32024-04-11 20:32:13 +08008149/**
8150 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8151 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8152 * the previous window should receive this event and not be dropped.
8153 */
8154TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8155 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008156 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8157 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008158 window->setFrame(Rect(0, 0, 100, 100));
8159 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8160
8161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8162 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8163 .build());
8164
8165 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8166
8167 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8168 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8169 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8170 .build());
8171
8172 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8173}
8174
8175/**
8176 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8177 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8178 * previous window should receive deviceB's event and it should be dropped.
8179 */
8180TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008182 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8183 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008184 window->setFrame(Rect(0, 0, 100, 100));
8185 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8186
8187 const DeviceId deviceA = 9;
8188 const DeviceId deviceB = 3;
8189
8190 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8191 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8192 .deviceId(deviceA)
8193 .build());
8194 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8195
8196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8197 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8198 .deviceId(deviceB)
8199 .build());
8200 window->assertNoEvents();
8201}
8202
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008203class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8204protected:
8205 std::shared_ptr<FakeApplicationHandle> mApp;
8206 sp<FakeWindowHandle> mWindow;
8207
8208 virtual void SetUp() override {
8209 InputDispatcherTest::SetUp();
8210
8211 mApp = std::make_shared<FakeApplicationHandle>();
8212
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008213 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8214 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008215 mWindow->setFrame(Rect(0, 0, 100, 100));
8216
8217 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8218 setFocusedWindow(mWindow);
8219 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8220 }
8221
8222 void setFallback(int32_t keycode) {
8223 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8224 return KeyEventBuilder(event).keyCode(keycode).build();
8225 });
8226 }
8227
8228 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008229 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8230 ASSERT_NE(nullptr, event);
8231 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008232 }
8233};
8234
8235TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8236 mDispatcher->notifyKey(
8237 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8238 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8239 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8240}
8241
8242TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8243 mDispatcher->notifyKey(
8244 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8245 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8246 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8247}
8248
8249TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8250 mDispatcher->notifyKey(
8251 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8252
8253 // Do not handle this key event.
8254 consumeKey(/*handled=*/false,
8255 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8256 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8257
8258 // Since the policy did not request any fallback to be generated, ensure there are no events.
8259 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8260}
8261
8262TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8263 setFallback(AKEYCODE_B);
8264 mDispatcher->notifyKey(
8265 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8266
8267 // Do not handle this key event.
8268 consumeKey(/*handled=*/false,
8269 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8270
8271 // Since the key was not handled, ensure the fallback event was dispatched instead.
8272 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8273 consumeKey(/*handled=*/true,
8274 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8275 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8276
8277 // Release the original key, and ensure the fallback key is also released.
8278 mDispatcher->notifyKey(
8279 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8280 consumeKey(/*handled=*/false,
8281 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8282 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8283 consumeKey(/*handled=*/true,
8284 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8285 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8286
8287 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8288 mWindow->assertNoEvents();
8289}
8290
8291TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8292 setFallback(AKEYCODE_B);
8293 mDispatcher->notifyKey(
8294 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8295
8296 // Do not handle this key event, but handle the fallback.
8297 consumeKey(/*handled=*/false,
8298 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8299 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8300 consumeKey(/*handled=*/true,
8301 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8302 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8303
8304 // Release the original key, and ensure the fallback key is also released.
8305 mDispatcher->notifyKey(
8306 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8307 // But this time, the app handles the original key.
8308 consumeKey(/*handled=*/true,
8309 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8310 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8311 // Ensure the fallback key is canceled.
8312 consumeKey(/*handled=*/true,
8313 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8314 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8315
8316 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8317 mWindow->assertNoEvents();
8318}
8319
8320TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8321 setFallback(AKEYCODE_B);
8322 mDispatcher->notifyKey(
8323 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8324
8325 // Do not handle this key event.
8326 consumeKey(/*handled=*/false,
8327 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8328 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8329 // App does not handle the fallback either, so ensure another fallback is not generated.
8330 setFallback(AKEYCODE_C);
8331 consumeKey(/*handled=*/false,
8332 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8333 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8334
8335 // Release the original key, and ensure the fallback key is also released.
8336 setFallback(AKEYCODE_B);
8337 mDispatcher->notifyKey(
8338 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8339 consumeKey(/*handled=*/false,
8340 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8341 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8342 consumeKey(/*handled=*/false,
8343 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8344 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8345
8346 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8347 mWindow->assertNoEvents();
8348}
8349
8350TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8351 setFallback(AKEYCODE_B);
8352 mDispatcher->notifyKey(
8353 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8354
8355 // Do not handle this key event, so fallback is generated.
8356 consumeKey(/*handled=*/false,
8357 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8358 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8359 consumeKey(/*handled=*/true,
8360 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8361 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8362
8363 // Release the original key, but assume the policy is misbehaving and it
8364 // generates an inconsistent fallback to the one from the DOWN event.
8365 setFallback(AKEYCODE_C);
8366 mDispatcher->notifyKey(
8367 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8368 consumeKey(/*handled=*/false,
8369 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8370 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8371 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8372 consumeKey(/*handled=*/true,
8373 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8374 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8375
8376 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8377 mWindow->assertNoEvents();
8378}
8379
8380TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8381 setFallback(AKEYCODE_B);
8382 mDispatcher->notifyKey(
8383 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8384
8385 // Do not handle this key event, so fallback is generated.
8386 consumeKey(/*handled=*/false,
8387 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8388 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8389 consumeKey(/*handled=*/true,
8390 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8391 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8392
8393 // The original key is canceled.
8394 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8395 .keyCode(AKEYCODE_A)
8396 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8397 .build());
8398 consumeKey(/*handled=*/false,
8399 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8400 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8401 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8402 // Ensure the fallback key is also canceled due to the original key being canceled.
8403 consumeKey(/*handled=*/true,
8404 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8405 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8406
8407 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8408 mWindow->assertNoEvents();
8409}
8410
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008411TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008412 setFallback(AKEYCODE_B);
8413 mDispatcher->notifyKey(
8414 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8415
8416 // Do not handle this key event.
8417 consumeKey(/*handled=*/false,
8418 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8419 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8420 consumeKey(/*handled=*/true,
8421 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8422 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8423
8424 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8425 // When the unhandled key is reported to the policy next, remove the input channel.
8426 mDispatcher->removeInputChannel(mWindow->getToken());
8427 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8428 });
8429 // Release the original key, and let the app now handle the previously unhandled key.
8430 // This should result in the previously generated fallback key to be cancelled.
8431 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8432 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8433 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8434 // the policy call, we will now remove the input channel. Once the policy call returns, the
8435 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8436 // not cause any crashes.
8437 mDispatcher->notifyKey(
8438 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8439 consumeKey(/*handled=*/true,
8440 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8441 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8442}
8443
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008444TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8445 setFallback(AKEYCODE_B);
8446 mDispatcher->notifyKey(
8447 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8448
8449 // Do not handle this key event.
8450 consumeKey(/*handled=*/false,
8451 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8452 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8453 consumeKey(/*handled=*/true,
8454 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8455 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8456
8457 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8458 // When the unhandled key is reported to the policy next, remove the window.
8459 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8460 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8461 });
8462 // Release the original key, which the app will not handle. When this unhandled key is reported
8463 // to the policy, the window will be removed.
8464 mDispatcher->notifyKey(
8465 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8466 consumeKey(/*handled=*/false,
8467 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8468 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8469
8470 // Since the window was removed, it loses focus, and the channel state will be reset.
8471 consumeKey(/*handled=*/true,
8472 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8473 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8474 mWindow->consumeFocusEvent(false);
8475 mWindow->assertNoEvents();
8476}
8477
8478TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8479 setFallback(AKEYCODE_B);
8480 mDispatcher->notifyKey(
8481 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8482
8483 // Do not handle this key event.
8484 consumeKey(/*handled=*/false,
8485 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8486 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8487 const auto [seq, event] = mWindow->receiveEvent();
8488 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8489 ASSERT_EQ(event->getType(), InputEventType::KEY);
8490 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8491 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8492 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8493
8494 // Remove the window now, which should generate a cancellations and make the window lose focus.
8495 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8496 consumeKey(/*handled=*/true,
8497 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8498 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8499 consumeKey(/*handled=*/true,
8500 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8501 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8502 mWindow->consumeFocusEvent(false);
8503
8504 // Finish the event by reporting it as handled.
8505 mWindow->finishEvent(*seq);
8506 mWindow->assertNoEvents();
8507}
8508
Garfield Tan1c7bc862020-01-28 13:24:04 -08008509class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8510protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008511 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8512 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008513
Chris Yea209fde2020-07-22 13:54:51 -07008514 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008515 sp<FakeWindowHandle> mWindow;
8516
8517 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008518 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008519
Prabir Pradhandae52792023-12-15 07:36:40 +00008520 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008521 setUpWindow();
8522 }
8523
8524 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008525 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008526 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8527 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008528
Vishnu Nair47074b82020-08-14 11:54:47 -07008529 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008530 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008531 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008532 mWindow->consumeFocusEvent(true);
8533 }
8534
Chris Ye2ad95392020-09-01 13:44:44 -07008535 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008536 NotifyKeyArgs keyArgs =
8537 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008538 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008539 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008540 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008541
8542 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008543 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008544 }
8545
8546 void expectKeyRepeatOnce(int32_t repeatCount) {
8547 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008548 mWindow->consumeKeyEvent(
8549 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008550 }
8551
Chris Ye2ad95392020-09-01 13:44:44 -07008552 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008553 NotifyKeyArgs keyArgs =
8554 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008555 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008556 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008557 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008558
8559 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008560 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008561 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008562 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008563
8564 void injectKeyRepeat(int32_t repeatCount) {
8565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008566 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8567 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008568 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8569 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008570};
8571
8572TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008573 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008574 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8575 expectKeyRepeatOnce(repeatCount);
8576 }
8577}
8578
8579TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008580 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008581 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8582 expectKeyRepeatOnce(repeatCount);
8583 }
Harry Cutts33476232023-01-30 19:57:29 +00008584 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008585 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008586 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8587 expectKeyRepeatOnce(repeatCount);
8588 }
8589}
8590
8591TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008592 sendAndConsumeKeyDown(/*deviceId=*/1);
8593 expectKeyRepeatOnce(/*repeatCount=*/1);
8594 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008595 mWindow->assertNoEvents();
8596}
8597
8598TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008599 sendAndConsumeKeyDown(/*deviceId=*/1);
8600 expectKeyRepeatOnce(/*repeatCount=*/1);
8601 sendAndConsumeKeyDown(/*deviceId=*/2);
8602 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008603 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008604 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008605 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008606 expectKeyRepeatOnce(/*repeatCount=*/2);
8607 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008608 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008609 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008610 mWindow->assertNoEvents();
8611}
8612
8613TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008614 sendAndConsumeKeyDown(/*deviceId=*/1);
8615 expectKeyRepeatOnce(/*repeatCount=*/1);
8616 sendAndConsumeKeyDown(/*deviceId=*/2);
8617 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008618 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008619 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008620 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008621 mWindow->assertNoEvents();
8622}
8623
liushenxiang42232912021-05-21 20:24:09 +08008624TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8625 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008626 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008627 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008628 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008629 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8630 mWindow->assertNoEvents();
8631}
8632
Garfield Tan1c7bc862020-01-28 13:24:04 -08008633TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008634 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008635 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008636 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008637 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8638 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008639 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008640 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008641 }
8642}
8643
8644TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008645 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008646 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008647
8648 std::unordered_set<int32_t> idSet;
8649 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008650 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8651 ASSERT_NE(nullptr, repeatEvent);
8652 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008653 EXPECT_EQ(idSet.end(), idSet.find(id));
8654 idSet.insert(id);
8655 }
8656}
8657
Hu Guofe3c8f12023-09-22 17:20:15 +08008658TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8659 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008660 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008661 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8662 expectKeyRepeatOnce(repeatCount);
8663 }
8664 injectKeyRepeat(1);
8665 // Expect repeatCount to be 3 instead of 1
8666 expectKeyRepeatOnce(3);
8667}
8668
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008669/* Test InputDispatcher for MultiDisplay */
8670class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8671public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008672 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008673 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008674
Chris Yea209fde2020-07-22 13:54:51 -07008675 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008676 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8677 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008678
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008679 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008680 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008681 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008682 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8683
Vishnu Nair958da932020-08-21 17:12:37 -07008684 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008685 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008686
Chris Yea209fde2020-07-22 13:54:51 -07008687 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008688 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008689 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008690 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008691 // Set focus display to second one.
8692 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00008693 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
8694
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008695 // Set focus window for second display.
8696 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008697 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008698 mDispatcher->onWindowInfosChanged(
8699 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008700 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008701 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008702 }
8703
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008704 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008705 InputDispatcherTest::TearDown();
8706
Chris Yea209fde2020-07-22 13:54:51 -07008707 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008708 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008709 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008710 windowInSecondary.clear();
8711 }
8712
8713protected:
Chris Yea209fde2020-07-22 13:54:51 -07008714 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008715 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008716 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008717 sp<FakeWindowHandle> windowInSecondary;
8718};
8719
8720TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8721 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008723 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8724 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008726 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008727 windowInSecondary->assertNoEvents();
8728
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008729 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008733 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008734 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008735}
8736
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008737TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008738 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008740 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008741 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008742 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08008743 windowInSecondary->assertNoEvents();
8744
8745 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008747 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008748 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008749 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008750
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008751 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008752 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08008753
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008754 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008755 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08008756
8757 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008758 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08008759 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008760 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08008761 windowInSecondary->assertNoEvents();
8762}
8763
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008764// Test per-display input monitors for motion event.
8765TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08008766 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008767 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008768 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008769 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008770
8771 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008773 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8774 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008776 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8777 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008778 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008779 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008780
8781 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008783 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008785 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008786 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008787 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08008788 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008789
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008790 // Lift up the touch from the second display
8791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008792 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008793 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8794 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
8795 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
8796
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008797 // Test inject a non-pointer motion event.
8798 // If specific a display, it will dispatch to the focused window of particular display,
8799 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
8802 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008804 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008805 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008806 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
8807 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008808}
8809
8810// Test per-display input monitors for key event.
8811TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008812 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08008813 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008814 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008815 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008816 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008817
8818 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008820 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008821 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008822 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008823 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8824 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008825}
8826
Vishnu Nair958da932020-08-21 17:12:37 -07008827TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
8828 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008829 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
8830 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008831 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008832 mDispatcher->onWindowInfosChanged(
8833 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
8834 *windowInSecondary->getInfo()},
8835 {},
8836 0,
8837 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008838 setFocusedWindow(secondWindowInPrimary);
8839 windowInPrimary->consumeFocusEvent(false);
8840 secondWindowInPrimary->consumeFocusEvent(true);
8841
8842 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008844 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008845 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008846 windowInPrimary->assertNoEvents();
8847 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008848 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008849}
8850
Arthur Hungdfd528e2021-12-08 13:23:04 +00008851TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
8852 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008853 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008854 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008855 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008856
8857 // Test touch down on primary display.
8858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008859 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8860 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008862 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8863 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008864
8865 // Test touch down on second display.
8866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008867 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8869 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
8870 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
8871
8872 // Trigger cancel touch.
8873 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008874 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
8875 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008876 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
8877 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
8878
8879 // Test inject a move motion event, no window/monitor should receive the event.
8880 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008881 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008882 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008883 << "Inject motion event should return InputEventInjectionResult::FAILED";
8884 windowInPrimary->assertNoEvents();
8885 monitorInPrimary.assertNoEvents();
8886
8887 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008888 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00008889 SECOND_DISPLAY_ID, {110, 200}))
8890 << "Inject motion event should return InputEventInjectionResult::FAILED";
8891 windowInSecondary->assertNoEvents();
8892 monitorInSecondary.assertNoEvents();
8893}
8894
Hu Guocb134f12023-12-23 13:42:44 +00008895/**
8896 * Send a key to the primary display and to the secondary display.
8897 * Then cause the key on the primary display to be canceled by sending in a stale key.
8898 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
8899 * does not get canceled.
8900 */
8901TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
8902 // Send a key down on primary display
8903 mDispatcher->notifyKey(
8904 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008905 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008906 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8907 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008908 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
8909 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008910 windowInSecondary->assertNoEvents();
8911
8912 // Send a key down on second display
8913 mDispatcher->notifyKey(
8914 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8915 .displayId(SECOND_DISPLAY_ID)
8916 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8917 .build());
8918 windowInSecondary->consumeKeyEvent(
8919 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8920 windowInPrimary->assertNoEvents();
8921
8922 // Send a valid key up event on primary display that will be dropped because it is stale
8923 NotifyKeyArgs staleKeyUp =
8924 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008925 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008926 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8927 .build();
8928 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8929 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8930 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8931 mDispatcher->notifyKey(staleKeyUp);
8932
8933 // Only the key gesture corresponding to the dropped event should receive the cancel event.
8934 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
8935 // receive any events.
8936 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008937 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00008938 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8939 windowInSecondary->assertNoEvents();
8940}
8941
8942/**
8943 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
8944 */
8945TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
8946 // Send touch down on primary display.
8947 mDispatcher->notifyMotion(
8948 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8949 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008950 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008951 .build());
8952 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008953 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008954 windowInSecondary->assertNoEvents();
8955
8956 // Send touch down on second display.
8957 mDispatcher->notifyMotion(
8958 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8959 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8960 .displayId(SECOND_DISPLAY_ID)
8961 .build());
8962 windowInPrimary->assertNoEvents();
8963 windowInSecondary->consumeMotionEvent(
8964 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8965
8966 // inject a valid MotionEvent on primary display that will be stale when it arrives.
8967 NotifyMotionArgs staleMotionUp =
8968 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008969 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008970 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8971 .build();
8972 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8973 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8974 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8975 mDispatcher->notifyMotion(staleMotionUp);
8976
8977 // For stale motion events, we let the gesture to complete. This behaviour is different from key
8978 // events, where we would cancel the current keys instead.
8979 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
8980 windowInSecondary->assertNoEvents();
8981}
8982
Jackal Guof9696682018-10-05 12:23:23 +08008983class InputFilterTest : public InputDispatcherTest {
8984protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08008985 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008986 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08008987 NotifyMotionArgs motionArgs;
8988
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008989 motionArgs =
8990 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008991 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008992 motionArgs =
8993 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008994 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008995 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008996 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008997 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008998 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08008999 } else {
9000 mFakePolicy->assertFilterInputEventWasNotCalled();
9001 }
9002 }
9003
9004 void testNotifyKey(bool expectToBeFiltered) {
9005 NotifyKeyArgs keyArgs;
9006
9007 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009008 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009009 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009010 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009011 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009012
9013 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009014 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009015 } else {
9016 mFakePolicy->assertFilterInputEventWasNotCalled();
9017 }
9018 }
9019};
9020
9021// Test InputFilter for MotionEvent
9022TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9023 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009024 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009025 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009026
9027 // Enable InputFilter
9028 mDispatcher->setInputFilterEnabled(true);
9029 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009030 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009031 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009032
9033 // Disable InputFilter
9034 mDispatcher->setInputFilterEnabled(false);
9035 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009036 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009037 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009038}
9039
9040// Test InputFilter for KeyEvent
9041TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9042 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009043 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009044
9045 // Enable InputFilter
9046 mDispatcher->setInputFilterEnabled(true);
9047 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009048 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009049
9050 // Disable InputFilter
9051 mDispatcher->setInputFilterEnabled(false);
9052 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009053 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009054}
9055
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009056// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9057// logical display coordinate space.
9058TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9059 ui::Transform firstDisplayTransform;
9060 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9061 ui::Transform secondDisplayTransform;
9062 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9063
9064 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009065 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009066 displayInfos[0].transform = firstDisplayTransform;
9067 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9068 displayInfos[1].transform = secondDisplayTransform;
9069
Patrick Williamsd828f302023-04-28 17:52:08 -05009070 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009071
9072 // Enable InputFilter
9073 mDispatcher->setInputFilterEnabled(true);
9074
9075 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009076 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9077 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009078 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009079}
9080
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009081class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9082protected:
9083 virtual void SetUp() override {
9084 InputDispatcherTest::SetUp();
9085
9086 /**
9087 * We don't need to enable input filter to test the injected event policy, but we enabled it
9088 * here to make the tests more realistic, since this policy only matters when inputfilter is
9089 * on.
9090 */
9091 mDispatcher->setInputFilterEnabled(true);
9092
9093 std::shared_ptr<InputApplicationHandle> application =
9094 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009095 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009096 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009097
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009098 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009099 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009100 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009101 setFocusedWindow(mWindow);
9102 mWindow->consumeFocusEvent(true);
9103 }
9104
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009105 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9106 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009107 KeyEvent event;
9108
9109 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9110 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009111 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9112 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009113 const int32_t additionalPolicyFlags =
9114 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009116 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009117 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009118 policyFlags | additionalPolicyFlags));
9119
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009120 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009121 }
9122
9123 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9124 int32_t flags) {
9125 MotionEvent event;
9126 PointerProperties pointerProperties[1];
9127 PointerCoords pointerCoords[1];
9128 pointerProperties[0].clear();
9129 pointerProperties[0].id = 0;
9130 pointerCoords[0].clear();
9131 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9132 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9133
9134 ui::Transform identityTransform;
9135 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9136 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9137 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9138 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9139 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009140 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009141 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009142 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009143
9144 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009146 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009147 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009148 policyFlags | additionalPolicyFlags));
9149
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009150 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009151 }
9152
9153private:
9154 sp<FakeWindowHandle> mWindow;
9155};
9156
9157TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009158 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9159 // filter. Without it, the event will no different from a regularly injected event, and the
9160 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009161 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9162 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009163}
9164
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009165TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009166 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009167 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009168 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9169}
9170
9171TEST_F(InputFilterInjectionPolicyTest,
9172 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9173 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009174 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009175 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009176}
9177
9178TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009179 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9180 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009181}
9182
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009183class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9184protected:
9185 virtual void SetUp() override {
9186 InputDispatcherTest::SetUp();
9187
9188 std::shared_ptr<FakeApplicationHandle> application =
9189 std::make_shared<FakeApplicationHandle>();
9190 application->setDispatchingTimeout(100ms);
9191 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009192 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009193 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009194 mWindow->setDispatchingTimeout(100ms);
9195 mWindow->setFocusable(true);
9196
9197 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009198 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009199
9200 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9201 setFocusedWindow(mWindow);
9202 mWindow->consumeFocusEvent(true);
9203 }
9204
Linnan Li13bf76a2024-05-05 19:18:02 +08009205 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009206 nsecs_t eventTime) {
9207 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9208 .displayId(displayId)
9209 .eventTime(eventTime)
9210 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9211 .build());
9212 mWindow->consumeMotionEvent(WithMotionAction(action));
9213 }
9214
9215private:
9216 sp<FakeWindowHandle> mWindow;
9217};
9218
9219TEST_F_WITH_FLAGS(
9220 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9221 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9222 rate_limit_user_activity_poke_in_dispatcher))) {
9223 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9224
9225 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009226 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009227 milliseconds_to_nanoseconds(50));
9228 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009229 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9230 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009231
9232 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009233 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009234 milliseconds_to_nanoseconds(130));
9235 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009236 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9237 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009238
9239 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009240 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9241 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009242 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009243 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9244 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009245
9246 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009247 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009248 milliseconds_to_nanoseconds(140));
9249 mFakePolicy->assertUserActivityNotPoked();
9250
9251 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009252 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9253 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009254 mFakePolicy->assertUserActivityNotPoked();
9255
9256 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9257 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009258 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009259 milliseconds_to_nanoseconds(160));
9260 mFakePolicy->assertUserActivityNotPoked();
9261
9262 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009263 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9264 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009265 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009266 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9267 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009268
9269 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009270 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009271 milliseconds_to_nanoseconds(300));
9272 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009273 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9274 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009275
9276 // Assert that there's no more user activity poke event.
9277 mFakePolicy->assertUserActivityNotPoked();
9278}
9279
9280TEST_F_WITH_FLAGS(
9281 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9282 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9283 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009284 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009285 milliseconds_to_nanoseconds(200));
9286 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009287 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9288 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009289
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009290 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009291 milliseconds_to_nanoseconds(280));
9292 mFakePolicy->assertUserActivityNotPoked();
9293
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009294 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009295 milliseconds_to_nanoseconds(340));
9296 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009297 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9298 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009299}
9300
9301TEST_F_WITH_FLAGS(
9302 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9303 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9304 rate_limit_user_activity_poke_in_dispatcher))) {
9305 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9306
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009307 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9308 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009309 mFakePolicy->assertUserActivityPoked();
9310
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009311 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9312 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009313 mFakePolicy->assertUserActivityPoked();
9314}
9315
chaviwfd6d3512019-03-25 13:23:49 -07009316class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009317 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009318 InputDispatcherTest::SetUp();
9319
Chris Yea209fde2020-07-22 13:54:51 -07009320 std::shared_ptr<FakeApplicationHandle> application =
9321 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009322 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9323 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009324 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009325
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009326 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9327 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009328 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009329
9330 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009331 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009332 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009333
9334 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009335 mDispatcher->onWindowInfosChanged(
9336 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009337 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009338 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009339 }
9340
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009341 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009342 InputDispatcherTest::TearDown();
9343
9344 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009345 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009346 }
9347
9348protected:
9349 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009350 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009351 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009352};
9353
9354// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9355// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9356// the onPointerDownOutsideFocus callback.
9357TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009359 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9360 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009361 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009362 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009363
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009364 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009365 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9366}
9367
9368// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9369// DOWN on the window that doesn't have focus. Ensure no window received the
9370// onPointerDownOutsideFocus callback.
9371TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009373 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009374 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009375 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009376 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009377
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009378 ASSERT_TRUE(mDispatcher->waitForIdle());
9379 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009380}
9381
9382// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9383// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9384TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009386 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009387 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009388 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009389
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009390 ASSERT_TRUE(mDispatcher->waitForIdle());
9391 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009392}
9393
9394// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9395// DOWN on the window that already has focus. Ensure no window received the
9396// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009397TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009399 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9400 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009401 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009402 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009403
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009404 ASSERT_TRUE(mDispatcher->waitForIdle());
9405 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009406}
9407
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009408// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9409// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9410TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9411 const MotionEvent event =
9412 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9413 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009414 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009415 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9416 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009419 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9420 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009421
9422 ASSERT_TRUE(mDispatcher->waitForIdle());
9423 mFakePolicy->assertOnPointerDownWasNotCalled();
9424 // Ensure that the unfocused window did not receive any FOCUS events.
9425 mUnfocusedWindow->assertNoEvents();
9426}
9427
chaviwaf87b3e2019-10-01 16:59:28 -07009428// These tests ensures we can send touch events to a single client when there are multiple input
9429// windows that point to the same client token.
9430class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9431 virtual void SetUp() override {
9432 InputDispatcherTest::SetUp();
9433
Chris Yea209fde2020-07-22 13:54:51 -07009434 std::shared_ptr<FakeApplicationHandle> application =
9435 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009436 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009437 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009438 mWindow1->setFrame(Rect(0, 0, 100, 100));
9439
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009440 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009441 mWindow2->setFrame(Rect(100, 100, 200, 200));
9442
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009443 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009444 }
9445
9446protected:
9447 sp<FakeWindowHandle> mWindow1;
9448 sp<FakeWindowHandle> mWindow2;
9449
9450 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009451 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009452 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9453 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009454 }
9455
9456 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9457 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009458 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009459 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009460 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009461 ASSERT_NE(nullptr, motionEvent);
9462 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009463
9464 for (size_t i = 0; i < points.size(); i++) {
9465 float expectedX = points[i].x;
9466 float expectedY = points[i].y;
9467
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009468 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009469 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009470 << ", got " << motionEvent->getX(i);
9471 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009472 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009473 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009474 }
9475 }
chaviw9eaa22c2020-07-01 16:21:27 -07009476
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009477 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9478 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009479 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009480 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009481 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009482
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009483 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009484 }
chaviwaf87b3e2019-10-01 16:59:28 -07009485};
9486
9487TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9488 // Touch Window 1
9489 PointF touchedPoint = {10, 10};
9490 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009491 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009492
9493 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009494 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009495
9496 // Touch Window 2
9497 touchedPoint = {150, 150};
9498 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009499 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009500}
9501
chaviw9eaa22c2020-07-01 16:21:27 -07009502TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9503 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009504 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009505 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009506
9507 // Touch Window 1
9508 PointF touchedPoint = {10, 10};
9509 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009510 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009511 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009512 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009513
9514 // Touch Window 2
9515 touchedPoint = {150, 150};
9516 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009517 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9518 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009519
chaviw9eaa22c2020-07-01 16:21:27 -07009520 // Update the transform so rotation is set
9521 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009522 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009523 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009524 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009525}
9526
chaviw9eaa22c2020-07-01 16:21:27 -07009527TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009528 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009529 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009530
9531 // Touch Window 1
9532 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9533 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009534 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009535
9536 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009537 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9538 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9539 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009540 touchedPoints.push_back(PointF{150, 150});
9541 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009542 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009543
chaviw9eaa22c2020-07-01 16:21:27 -07009544 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009545 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009546 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009547
chaviw9eaa22c2020-07-01 16:21:27 -07009548 // Update the transform so rotation is set for Window 2
9549 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009550 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009551 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009552 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009553}
9554
chaviw9eaa22c2020-07-01 16:21:27 -07009555TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009556 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009557 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009558
9559 // Touch Window 1
9560 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9561 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009562 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009563
9564 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009565 touchedPoints.push_back(PointF{150, 150});
9566 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009567
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009568 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009569
9570 // Move both windows
9571 touchedPoints = {{20, 20}, {175, 175}};
9572 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9573 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9574
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009575 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009576
chaviw9eaa22c2020-07-01 16:21:27 -07009577 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009578 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009579 expectedPoints.pop_back();
9580
9581 // Touch Window 2
9582 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009583 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009584 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009585 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009586
9587 // Move both windows
9588 touchedPoints = {{20, 20}, {175, 175}};
9589 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9590 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9591
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009592 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009593}
9594
9595TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9596 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009597 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009598
9599 // Touch Window 1
9600 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9601 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009602 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009603
9604 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009605 touchedPoints.push_back(PointF{150, 150});
9606 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009607
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009608 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009609
9610 // Move both windows
9611 touchedPoints = {{20, 20}, {175, 175}};
9612 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9613 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9614
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009615 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009616}
9617
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009618/**
9619 * When one of the windows is slippery, the touch should not slip into the other window with the
9620 * same input channel.
9621 */
9622TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9623 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009624 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009625
9626 // Touch down in window 1
9627 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009628 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009629 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9630
9631 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9632 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9633 // getting generated.
9634 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009635 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009636
9637 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9638}
9639
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009640/**
9641 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9642 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9643 * that the pointer is hovering over may have a different transform.
9644 */
9645TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009646 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009647
9648 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9650 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9651 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009652 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9653 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009654 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009655 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9656 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9657 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009658 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009659 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009660 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9661}
9662
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009663class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9664 virtual void SetUp() override {
9665 InputDispatcherTest::SetUp();
9666
Chris Yea209fde2020-07-22 13:54:51 -07009667 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009668 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009669 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009670 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009671 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009672 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009673 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009674
9675 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009676 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009677
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009678 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009679 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009680 mWindow->consumeFocusEvent(true);
9681 }
9682
9683 virtual void TearDown() override {
9684 InputDispatcherTest::TearDown();
9685 mWindow.clear();
9686 }
9687
9688protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009689 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009690 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009691 sp<FakeWindowHandle> mWindow;
9692 static constexpr PointF WINDOW_LOCATION = {20, 20};
9693
9694 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009695 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9696 .x(WINDOW_LOCATION.x)
9697 .y(WINDOW_LOCATION.y);
9698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9699 .pointer(touchingPointer)
9700 .build());
9701 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9702 .pointer(touchingPointer)
9703 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009704 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009705
9706 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009707 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9708 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009709 spy->setTrustedOverlay(true);
9710 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009711 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009712 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009713 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009714 return spy;
9715 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009716};
9717
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009718// Send a tap and respond, which should not cause an ANR.
9719TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9720 tapOnWindow();
9721 mWindow->consumeMotionDown();
9722 mWindow->consumeMotionUp();
9723 ASSERT_TRUE(mDispatcher->waitForIdle());
9724 mFakePolicy->assertNotifyAnrWasNotCalled();
9725}
9726
9727// Send a regular key and respond, which should not cause an ANR.
9728TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009730 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009731 ASSERT_TRUE(mDispatcher->waitForIdle());
9732 mFakePolicy->assertNotifyAnrWasNotCalled();
9733}
9734
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009735TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9736 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009737 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009738 mWindow->consumeFocusEvent(false);
9739
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009740 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009741 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9742 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
9743 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00009744 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009746 // Key will not go to window because we have no focused window.
9747 // The 'no focused window' ANR timer should start instead.
9748
9749 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009750 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009751 // The key should get dropped and there should be no ANR.
9752
9753 ASSERT_TRUE(mDispatcher->waitForIdle());
9754 mFakePolicy->assertNotifyAnrWasNotCalled();
9755}
9756
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009757// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009758// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9759// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009760TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009762 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9763 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009764
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009765 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009766 ASSERT_TRUE(sequenceNum);
9767 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009768 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009769
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009770 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009771 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009772 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009773 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009774 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009775}
9776
9777// Send a key to the app and have the app not respond right away.
9778TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
9779 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009781 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009782 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009783 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009784 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009785 ASSERT_TRUE(mDispatcher->waitForIdle());
9786}
9787
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009788// We have a focused application, but no focused window
9789TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009790 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009791 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009792 mWindow->consumeFocusEvent(false);
9793
9794 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009796 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9797 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009798 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9799 mDispatcher->waitForIdle();
9800 mFakePolicy->assertNotifyAnrWasNotCalled();
9801
9802 // Once a focused event arrives, we get an ANR for this application
9803 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9804 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009805 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009806 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9807 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +08009808 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009809 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009810 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07009811 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009812 ASSERT_TRUE(mDispatcher->waitForIdle());
9813}
9814
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009815/**
9816 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
9817 * there will not be an ANR.
9818 */
9819TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
9820 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009821 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009822 mWindow->consumeFocusEvent(false);
9823
9824 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07009825 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
9826 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009827 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
9828 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
9829
9830 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009831 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
9832 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
9833 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
9834 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009835
Hu Guofe3c8f12023-09-22 17:20:15 +08009836 const int32_t policyFlags =
9837 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009838
9839 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00009840 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009841 InputEventInjectionSync::WAIT_FOR_RESULT,
9842 INJECT_EVENT_TIMEOUT, policyFlags);
9843 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
9844 << "Injection should fail because the event is stale";
9845
9846 ASSERT_TRUE(mDispatcher->waitForIdle());
9847 mFakePolicy->assertNotifyAnrWasNotCalled();
9848 mWindow->assertNoEvents();
9849}
9850
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009851// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009852// Make sure that we don't notify policy twice about the same ANR.
9853TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009854 const std::chrono::duration appTimeout = 400ms;
9855 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009856 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009857
Vishnu Nair47074b82020-08-14 11:54:47 -07009858 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009859 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009860 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009861
9862 // Once a focused event arrives, we get an ANR for this application
9863 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9864 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009865 const std::chrono::duration eventInjectionTimeout = 100ms;
9866 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009867 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009868 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9869 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
9870 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009871 /*allowKeyRepeat=*/false);
9872 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
9873 << "result=" << ftl::enum_string(result);
9874 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
9875 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
9876 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
9877 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009878
Vishnu Naire4df8752022-09-08 09:17:55 -07009879 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009880 // ANR should not be raised again. It is up to policy to do that if it desires.
9881 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009882
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009883 // If we now get a focused window, the ANR should stop, but the policy handles that via
9884 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009885 ASSERT_TRUE(mDispatcher->waitForIdle());
9886}
9887
9888// We have a focused application, but no focused window
9889TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009890 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009891 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009892 mWindow->consumeFocusEvent(false);
9893
9894 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009895 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009896
Vishnu Naire4df8752022-09-08 09:17:55 -07009897 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9898 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009899
9900 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009901 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009902 ASSERT_TRUE(mDispatcher->waitForIdle());
9903 mWindow->assertNoEvents();
9904}
9905
9906/**
9907 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
9908 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
9909 * If we process 1 of the events, but ANR on the second event with the same timestamp,
9910 * the ANR mechanism should still work.
9911 *
9912 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
9913 * DOWN event, while not responding on the second one.
9914 */
9915TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
9916 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009917 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009918 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009919 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9920 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009921 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009922
9923 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009924 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009925 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009926 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9927 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009928 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009929
9930 // 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 -07009931 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009932 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009933 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009934}
9935
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009936// A spy window can receive an ANR
9937TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
9938 sp<FakeWindowHandle> spy = addSpyWindow();
9939
9940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009941 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9942 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009943 mWindow->consumeMotionDown();
9944
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009945 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009946 ASSERT_TRUE(sequenceNum);
9947 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009948 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009949
9950 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009951 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009952 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009953 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009954 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009955}
9956
9957// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009958// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009959TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
9960 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009961
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009963 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
9964 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9966 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009967
9968 // Stuck on the ACTION_UP
9969 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009970 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009971
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009972 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009973 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009974 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9975 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009976
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009977 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009978 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009979 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009980 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009981 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009982}
9983
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009984// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009985// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009986TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
9987 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009988
9989 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009990 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9991 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009992
9993 mWindow->consumeMotionDown();
9994 // Stuck on the ACTION_UP
9995 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009996 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009997
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009998 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009999 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010000 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10001 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010002
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010003 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010004 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010005 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010006 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010007 spy->assertNoEvents();
10008}
10009
10010TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010011 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010012
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010013 FakeMonitorReceiver monitor =
10014 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010015
10016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010017 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10018 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010019
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010020 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010021 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10022 ASSERT_TRUE(consumeSeq);
10023
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010024 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10025 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010026
10027 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010028 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010029
10030 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010031 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010032}
10033
10034// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10035// process events, you don't get an anr. When the window later becomes unresponsive again, you
10036// get an ANR again.
10037// 1. tap -> block on ACTION_UP -> receive ANR
10038// 2. consume all pending events (= queue becomes healthy again)
10039// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10040TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10041 tapOnWindow();
10042
10043 mWindow->consumeMotionDown();
10044 // Block on ACTION_UP
10045 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010046 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010047 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10048 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010049 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010050 mWindow->assertNoEvents();
10051
10052 tapOnWindow();
10053 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010054 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010055 mWindow->consumeMotionUp();
10056
10057 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010058 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010059 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010060 mWindow->assertNoEvents();
10061}
10062
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010063// If a connection remains unresponsive for a while, make sure policy is only notified once about
10064// it.
10065TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010067 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10068 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010069
10070 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010071 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010072 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010073 // 'notifyConnectionUnresponsive' should only be called once per connection
10074 mFakePolicy->assertNotifyAnrWasNotCalled();
10075 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010076 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010077 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010078 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010079 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010080 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010081 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010082 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010083}
10084
10085/**
10086 * 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 -070010087 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010088 */
10089TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010090 // The timeouts in this test are established by relying on the fact that the "key waiting for
10091 // events timeout" is equal to 500ms.
10092 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010093 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010094 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010095
10096 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010097 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010098 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010099 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010100 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010101
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010102 // Don't finish the events yet, and send a key
10103 mDispatcher->notifyKey(
10104 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10105 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10106 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010107 // Key will not be sent to the window, yet, because the window is still processing events
10108 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010109 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010110 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010111
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010112 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010113 // if we wait long enough though, dispatcher will give up, and still send the key
10114 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010115 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010116 mWindow->finishEvent(*downSequenceNum);
10117 mWindow->finishEvent(*upSequenceNum);
10118}
10119
10120/**
10121 * If a window is processing a motion event, and then a key event comes in, the key event should
10122 * not go to the focused window until the motion is processed.
10123 * If then a new motion comes in, then the pending key event should be going to the currently
10124 * focused window right away.
10125 */
10126TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010127 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10128 // The timeouts in this test are established by relying on the fact that the "key waiting for
10129 // events timeout" is equal to 500ms.
10130 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010131 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010132 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010133
10134 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010135 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010136 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010137 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010138 ASSERT_TRUE(upSequenceNum);
10139 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010140 mDispatcher->notifyKey(
10141 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10142 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10143 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010144 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010145 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010146
10147 // Now tap down again. It should cause the pending key to go to the focused window right away.
10148 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010149 // Now that we tapped, we should receive the key immediately.
10150 // Since there's still room for slowness, we use 200ms, which is much less than
10151 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10152 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10153 ASSERT_NE(nullptr, keyEvent);
10154 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10155 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10156 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10157 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010158 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10159 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010160 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10161 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010162 mWindow->assertNoEvents();
10163}
10164
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010165/**
10166 * Send an event to the app and have the app not respond right away.
10167 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10168 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10169 * At some point, the window becomes responsive again.
10170 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10171 */
10172TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10173 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10174 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10175 .build());
10176
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010177 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010178 ASSERT_TRUE(sequenceNum);
10179 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10180 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10181
10182 mWindow->finishEvent(*sequenceNum);
10183 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10184 ASSERT_TRUE(mDispatcher->waitForIdle());
10185 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10186
10187 // Now that the window is responsive, let's continue the gesture.
10188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10189 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10190 .build());
10191
10192 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10193 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10194 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10195 .build());
10196
10197 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10198 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10199 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10200 .build());
10201 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10202 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10203 .build());
10204 // We already canceled this pointer, so the window shouldn't get any new events.
10205 mWindow->assertNoEvents();
10206
10207 // Start another one.
10208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10209 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10210 .build());
10211 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10212}
10213
Prabir Pradhanfc364722024-02-08 17:51:20 +000010214// Send an event to the app and have the app not respond right away. Then remove the app window.
10215// When the window is removed, the dispatcher will cancel the events for that window.
10216// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10217TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10218 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010219 AINPUT_SOURCE_TOUCHSCREEN,
10220 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010221
10222 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10223 ASSERT_TRUE(sequenceNum);
10224
10225 // Remove the window, but the input channel should remain alive.
10226 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10227
10228 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10229 // Since the window was removed, Dispatcher does not know the PID associated with the window
10230 // anymore, so the policy is notified without the PID.
10231 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10232 /*pid=*/std::nullopt);
10233
10234 mWindow->finishEvent(*sequenceNum);
10235 // The cancellation was generated when the window was removed, along with the focus event.
10236 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010237 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010238 mWindow->consumeFocusEvent(false);
10239 ASSERT_TRUE(mDispatcher->waitForIdle());
10240 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10241}
10242
10243// Send an event to the app and have the app not respond right away. Wait for the policy to be
10244// notified of the unresponsive window, then remove the app window.
10245TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10246 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010247 AINPUT_SOURCE_TOUCHSCREEN,
10248 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010249
10250 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10251 ASSERT_TRUE(sequenceNum);
10252 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10253 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10254
10255 // Remove the window, but the input channel should remain alive.
10256 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10257
10258 mWindow->finishEvent(*sequenceNum);
10259 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10260 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010261 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010262 mWindow->consumeFocusEvent(false);
10263 ASSERT_TRUE(mDispatcher->waitForIdle());
10264 // Since the window was removed, Dispatcher does not know the PID associated with the window
10265 // becoming responsive, so the policy is notified without the PID.
10266 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10267}
10268
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010269class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10270 virtual void SetUp() override {
10271 InputDispatcherTest::SetUp();
10272
Chris Yea209fde2020-07-22 13:54:51 -070010273 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010274 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010275 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010276 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010277 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010278 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010279 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010280
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010281 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010282 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010283 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010284 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010285
10286 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010287 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010288 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010289
10290 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010291 mDispatcher->onWindowInfosChanged(
10292 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010293 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010294 mFocusedWindow->consumeFocusEvent(true);
10295 }
10296
10297 virtual void TearDown() override {
10298 InputDispatcherTest::TearDown();
10299
10300 mUnfocusedWindow.clear();
10301 mFocusedWindow.clear();
10302 }
10303
10304protected:
Chris Yea209fde2020-07-22 13:54:51 -070010305 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010306 sp<FakeWindowHandle> mUnfocusedWindow;
10307 sp<FakeWindowHandle> mFocusedWindow;
10308 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10309 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10310 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10311
10312 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10313
10314 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10315
10316private:
10317 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010319 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10320 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010322 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10323 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010324 }
10325};
10326
10327// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10328// should be ANR'd first.
10329TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010331 injectMotionEvent(*mDispatcher,
10332 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10333 AINPUT_SOURCE_TOUCHSCREEN)
10334 .pointer(PointerBuilder(0, ToolType::FINGER)
10335 .x(FOCUSED_WINDOW_LOCATION.x)
10336 .y(FOCUSED_WINDOW_LOCATION.y))
10337 .build()));
10338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10339 injectMotionEvent(*mDispatcher,
10340 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10341 AINPUT_SOURCE_TOUCHSCREEN)
10342 .pointer(PointerBuilder(0, ToolType::FINGER)
10343 .x(FOCUSED_WINDOW_LOCATION.x)
10344 .y(FOCUSED_WINDOW_LOCATION.y))
10345 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010346 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010347 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010348 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010349 // We consumed all events, so no ANR
10350 ASSERT_TRUE(mDispatcher->waitForIdle());
10351 mFakePolicy->assertNotifyAnrWasNotCalled();
10352
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010354 injectMotionEvent(*mDispatcher,
10355 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10356 AINPUT_SOURCE_TOUCHSCREEN)
10357 .pointer(PointerBuilder(0, ToolType::FINGER)
10358 .x(FOCUSED_WINDOW_LOCATION.x)
10359 .y(FOCUSED_WINDOW_LOCATION.y))
10360 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010361 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010362 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010363
10364 const std::chrono::duration timeout =
10365 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010366 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010367
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010368 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010369 mFocusedWindow->consumeMotionDown();
10370 // This cancel is generated because the connection was unresponsive
10371 mFocusedWindow->consumeMotionCancel();
10372 mFocusedWindow->assertNoEvents();
10373 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010374 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010375 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10376 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010377 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010378}
10379
10380// If we have 2 windows with identical timeouts that are both unresponsive,
10381// it doesn't matter which order they should have ANR.
10382// But we should receive ANR for both.
10383TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10384 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010385 mUnfocusedWindow->setDispatchingTimeout(
10386 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010387 mDispatcher->onWindowInfosChanged(
10388 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010389
10390 tapOnFocusedWindow();
10391 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010392 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010393 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10394 mFocusedWindow->getDispatchingTimeout(
10395 DISPATCHING_TIMEOUT)),
10396 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10397
10398 ASSERT_THAT(anrConnectionTokens,
10399 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10400 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010401
10402 ASSERT_TRUE(mDispatcher->waitForIdle());
10403 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010404
10405 mFocusedWindow->consumeMotionDown();
10406 mFocusedWindow->consumeMotionUp();
10407 mUnfocusedWindow->consumeMotionOutside();
10408
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010409 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10410 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010411
10412 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010413 ASSERT_THAT(responsiveTokens,
10414 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10415 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010416 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010417}
10418
10419// If a window is already not responding, the second tap on the same window should be ignored.
10420// We should also log an error to account for the dropped event (not tested here).
10421// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10422TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10423 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010424 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010425 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010426 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010427 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010428 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010429 ASSERT_TRUE(upEventSequenceNum);
10430 const std::chrono::duration timeout =
10431 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010432 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010433
10434 // Tap once again
10435 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010436 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010437 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10438 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010439 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010440 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010441 FOCUSED_WINDOW_LOCATION));
10442 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10443 // valid touch target
10444 mUnfocusedWindow->assertNoEvents();
10445
10446 // Consume the first tap
10447 mFocusedWindow->finishEvent(*downEventSequenceNum);
10448 mFocusedWindow->finishEvent(*upEventSequenceNum);
10449 ASSERT_TRUE(mDispatcher->waitForIdle());
10450 // The second tap did not go to the focused window
10451 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010452 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010453 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10454 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010455 mFakePolicy->assertNotifyAnrWasNotCalled();
10456}
10457
10458// If you tap outside of all windows, there will not be ANR
10459TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010460 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010461 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10462 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010463 ASSERT_TRUE(mDispatcher->waitForIdle());
10464 mFakePolicy->assertNotifyAnrWasNotCalled();
10465}
10466
10467// Since the focused window is paused, tapping on it should not produce any events
10468TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10469 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010470 mDispatcher->onWindowInfosChanged(
10471 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010472
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010473 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010474 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10475 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010476
10477 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10478 ASSERT_TRUE(mDispatcher->waitForIdle());
10479 // Should not ANR because the window is paused, and touches shouldn't go to it
10480 mFakePolicy->assertNotifyAnrWasNotCalled();
10481
10482 mFocusedWindow->assertNoEvents();
10483 mUnfocusedWindow->assertNoEvents();
10484}
10485
10486/**
10487 * 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 -070010488 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010489 * If a different window becomes focused at this time, the key should go to that window instead.
10490 *
10491 * Warning!!!
10492 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10493 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010494 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010495 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10496 *
10497 * If that value changes, this test should also change.
10498 */
10499TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10500 // Set a long ANR timeout to prevent it from triggering
10501 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010502 mDispatcher->onWindowInfosChanged(
10503 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010504
10505 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010506 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010507 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010508 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010509 ASSERT_TRUE(upSequenceNum);
10510 // Don't finish the events yet, and send a key
10511 // Injection will succeed because we will eventually give up and send the key to the focused
10512 // window even if motions are still being processed.
10513
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010514 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010515 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10516 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010517 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010519 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010520 // and the key remains pending, waiting for the touch events to be processed.
10521 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10522 // under the hood.
10523 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10524 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010525
10526 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010527 mFocusedWindow->setFocusable(false);
10528 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010529 mDispatcher->onWindowInfosChanged(
10530 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010531 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010532
10533 // Focus events should precede the key events
10534 mUnfocusedWindow->consumeFocusEvent(true);
10535 mFocusedWindow->consumeFocusEvent(false);
10536
10537 // Finish the tap events, which should unblock dispatcher
10538 mUnfocusedWindow->finishEvent(*downSequenceNum);
10539 mUnfocusedWindow->finishEvent(*upSequenceNum);
10540
10541 // Now that all queues are cleared and no backlog in the connections, the key event
10542 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010543 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010544 mFocusedWindow->assertNoEvents();
10545 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010546 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010547}
10548
10549// When the touch stream is split across 2 windows, and one of them does not respond,
10550// then ANR should be raised and the touch should be canceled for the unresponsive window.
10551// The other window should not be affected by that.
10552TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10553 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010554 mDispatcher->notifyMotion(
10555 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10556 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10557 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010558
10559 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010560 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010561 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10562 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010563 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010564
10565 const std::chrono::duration timeout =
10566 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010567 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010568
10569 mUnfocusedWindow->consumeMotionDown();
10570 mFocusedWindow->consumeMotionDown();
10571 // Focused window may or may not receive ACTION_MOVE
10572 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010573 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010574 ASSERT_TRUE(moveOrCancelSequenceNum);
10575 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10576 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010577 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010578 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10579 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10580 mFocusedWindow->consumeMotionCancel();
10581 } else {
10582 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10583 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010584 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010585 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10586 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010587
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010588 mUnfocusedWindow->assertNoEvents();
10589 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010590 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010591}
10592
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010593/**
10594 * If we have no focused window, and a key comes in, we start the ANR timer.
10595 * The focused application should add a focused window before the timer runs out to prevent ANR.
10596 *
10597 * If the user touches another application during this time, the key should be dropped.
10598 * Next, if a new focused window comes in, without toggling the focused application,
10599 * then no ANR should occur.
10600 *
10601 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10602 * but in some cases the policy may not update the focused application.
10603 */
10604TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10605 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10606 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010607 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010608 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010609 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10610 mFocusedWindow->setFocusable(false);
10611
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010612 mDispatcher->onWindowInfosChanged(
10613 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010614 mFocusedWindow->consumeFocusEvent(false);
10615
10616 // Send a key. The ANR timer should start because there is no focused window.
10617 // 'focusedApplication' will get blamed if this timer completes.
10618 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010619 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010620 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10621 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010622 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010623 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010625
10626 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10627 // then the injected touches won't cause the focused event to get dropped.
10628 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10629 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10630 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10631 // For this test, it means that the key would get delivered to the window once it becomes
10632 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010633 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010634
10635 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010636 mDispatcher->notifyMotion(
10637 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10638 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010639
10640 // We do not consume the motion right away, because that would require dispatcher to first
10641 // process (== drop) the key event, and by that time, ANR will be raised.
10642 // Set the focused window first.
10643 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010644 mDispatcher->onWindowInfosChanged(
10645 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010646 setFocusedWindow(mFocusedWindow);
10647 mFocusedWindow->consumeFocusEvent(true);
10648 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10649 // to another application. This could be a bug / behaviour in the policy.
10650
10651 mUnfocusedWindow->consumeMotionDown();
10652
10653 ASSERT_TRUE(mDispatcher->waitForIdle());
10654 // Should not ANR because we actually have a focused window. It was just added too slowly.
10655 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10656}
10657
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010658/**
10659 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10660 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10661 * dispatcher doesn't prune pointer events incorrectly.
10662 *
10663 * This test reproduces a crash in InputDispatcher.
10664 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10665 *
10666 * Keep the currently focused application (mApplication), and have no focused window.
10667 * We set up two additional windows:
10668 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10669 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10670 * window. This window is not focusable, but is touchable.
10671 *
10672 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10673 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10674 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10675 *
10676 * Now, we touch "Another window". This window is owned by a different application than
10677 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10678 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10679 * dropping the events from its queue. Ensure that no crash occurs.
10680 *
10681 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10682 * This does not affect the test running time.
10683 */
10684TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10685 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10686 std::make_shared<FakeApplicationHandle>();
10687 systemUiApplication->setDispatchingTimeout(3000ms);
10688 mFakePolicy->setStaleEventTimeout(3000ms);
10689 sp<FakeWindowHandle> navigationBar =
10690 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010691 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010692 navigationBar->setFocusable(false);
10693 navigationBar->setWatchOutsideTouch(true);
10694 navigationBar->setFrame(Rect(0, 0, 100, 100));
10695
10696 mApplication->setDispatchingTimeout(3000ms);
10697 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010698 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010699
10700 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10701 std::make_shared<FakeApplicationHandle>();
10702 sp<FakeWindowHandle> appWindow =
10703 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010704 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010705 appWindow->setFocusable(false);
10706 appWindow->setFrame(Rect(100, 100, 200, 200));
10707
10708 mDispatcher->onWindowInfosChanged(
10709 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10710 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10711 mFocusedWindow->consumeFocusEvent(false);
10712
10713 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10714 // in response.
10715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10716 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10717 .build());
10718 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10719
10720 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10721 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10722 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010723 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10724 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010725 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010726 /*allowKeyRepeat=*/false);
10727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10728
10729 // Finish the gesture - lift up finger and inject ACTION_UP key event
10730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10731 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10732 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010733 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10734 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010735 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010736 /*allowKeyRepeat=*/false);
10737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10738 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10739 // getting any events yet.
10740 navigationBar->assertNoEvents();
10741
10742 // Now touch "Another window". This touch is going to a different application than the one we
10743 // are waiting for (which is 'mApplication').
10744 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
10745 // trying to be injected) and to continue processing the rest of the events in the original
10746 // order.
10747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10748 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10749 .build());
10750 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
10751 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
10752 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10753
10754 appWindow->assertNoEvents();
10755 navigationBar->assertNoEvents();
10756}
10757
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010758// These tests ensure we cannot send touch events to a window that's positioned behind a window
10759// that has feature NO_INPUT_CHANNEL.
10760// Layout:
10761// Top (closest to user)
10762// mNoInputWindow (above all windows)
10763// mBottomWindow
10764// Bottom (furthest from user)
10765class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
10766 virtual void SetUp() override {
10767 InputDispatcherTest::SetUp();
10768
10769 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010770 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10771 "Window without input channel",
10772 ui::LogicalDisplayId::DEFAULT,
10773 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010774 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010775 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
10776 // It's perfectly valid for this window to not have an associated input channel
10777
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010778 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010779 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010780 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
10781
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010782 mDispatcher->onWindowInfosChanged(
10783 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010784 }
10785
10786protected:
10787 std::shared_ptr<FakeApplicationHandle> mApplication;
10788 sp<FakeWindowHandle> mNoInputWindow;
10789 sp<FakeWindowHandle> mBottomWindow;
10790};
10791
10792TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
10793 PointF touchedPoint = {10, 10};
10794
Prabir Pradhan678438e2023-04-13 19:32:51 +000010795 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010796 AINPUT_SOURCE_TOUCHSCREEN,
10797 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010798
10799 mNoInputWindow->assertNoEvents();
10800 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
10801 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
10802 // and therefore should prevent mBottomWindow from receiving touches
10803 mBottomWindow->assertNoEvents();
10804}
10805
10806/**
10807 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
10808 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
10809 */
10810TEST_F(InputDispatcherMultiWindowOcclusionTests,
10811 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010812 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10813 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010814 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010815
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010816 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010817 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010818 mDispatcher->onWindowInfosChanged(
10819 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010820
10821 PointF touchedPoint = {10, 10};
10822
Prabir Pradhan678438e2023-04-13 19:32:51 +000010823 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010824 AINPUT_SOURCE_TOUCHSCREEN,
10825 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010826
10827 mNoInputWindow->assertNoEvents();
10828 mBottomWindow->assertNoEvents();
10829}
10830
Vishnu Nair958da932020-08-21 17:12:37 -070010831class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
10832protected:
10833 std::shared_ptr<FakeApplicationHandle> mApp;
10834 sp<FakeWindowHandle> mWindow;
10835 sp<FakeWindowHandle> mMirror;
10836
10837 virtual void SetUp() override {
10838 InputDispatcherTest::SetUp();
10839 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010840 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10841 ui::LogicalDisplayId::DEFAULT);
10842 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
10843 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070010844 mWindow->setFocusable(true);
10845 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010846 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010847 }
10848};
10849
10850TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
10851 // Request focus on a mirrored window
10852 setFocusedWindow(mMirror);
10853
10854 // window gets focused
10855 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010857 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010858 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010859}
10860
10861// A focused & mirrored window remains focused only if the window and its mirror are both
10862// focusable.
10863TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
10864 setFocusedWindow(mMirror);
10865
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010866 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070010867 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010869 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010870 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010872 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010873 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010874
10875 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010876 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010877
10878 // window loses focus since one of the windows associated with the token in not focusable
10879 mWindow->consumeFocusEvent(false);
10880
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010881 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010882 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010883 mWindow->assertNoEvents();
10884}
10885
10886// A focused & mirrored window remains focused until the window and its mirror both become
10887// invisible.
10888TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
10889 setFocusedWindow(mMirror);
10890
10891 // window gets focused
10892 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010894 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010895 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010897 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010898 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010899
10900 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010901 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010902
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010904 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010905 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010907 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010908 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010909
10910 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010911 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010912
10913 // window loses focus only after all windows associated with the token become invisible.
10914 mWindow->consumeFocusEvent(false);
10915
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010916 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010917 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010918 mWindow->assertNoEvents();
10919}
10920
10921// A focused & mirrored window remains focused until both windows are removed.
10922TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
10923 setFocusedWindow(mMirror);
10924
10925 // window gets focused
10926 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010928 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010929 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010931 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010932 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010933
10934 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010935 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010936
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010938 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010939 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010941 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010942 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010943
10944 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010945 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010946 mWindow->consumeFocusEvent(false);
10947
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010948 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010949 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010950 mWindow->assertNoEvents();
10951}
10952
10953// Focus request can be pending until one window becomes visible.
10954TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
10955 // Request focus on an invisible mirror.
10956 mWindow->setVisible(false);
10957 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010958 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010959 setFocusedWindow(mMirror);
10960
10961 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010963 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010964 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070010965
10966 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010967 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010968
10969 // window gets focused
10970 mWindow->consumeFocusEvent(true);
10971 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010972 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070010973}
Prabir Pradhan99987712020-11-10 18:43:05 -080010974
10975class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
10976protected:
10977 std::shared_ptr<FakeApplicationHandle> mApp;
10978 sp<FakeWindowHandle> mWindow;
10979 sp<FakeWindowHandle> mSecondWindow;
10980
10981 void SetUp() override {
10982 InputDispatcherTest::SetUp();
10983 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010984 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10985 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010986 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010987 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
10988 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010989 mSecondWindow->setFocusable(true);
10990
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010991 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010992 mDispatcher->onWindowInfosChanged(
10993 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080010994
10995 setFocusedWindow(mWindow);
10996 mWindow->consumeFocusEvent(true);
10997 }
10998
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010999 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011000 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011001 }
11002
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011003 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11004 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011005 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011006 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011007 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011008 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011009 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011010 }
11011};
11012
11013TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11014 // Ensure that capture cannot be obtained for unfocused windows.
11015 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11016 mFakePolicy->assertSetPointerCaptureNotCalled();
11017 mSecondWindow->assertNoEvents();
11018
11019 // Ensure that capture can be enabled from the focus window.
11020 requestAndVerifyPointerCapture(mWindow, true);
11021
11022 // Ensure that capture cannot be disabled from a window that does not have capture.
11023 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11024 mFakePolicy->assertSetPointerCaptureNotCalled();
11025
11026 // Ensure that capture can be disabled from the window with capture.
11027 requestAndVerifyPointerCapture(mWindow, false);
11028}
11029
11030TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011031 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011032
11033 setFocusedWindow(mSecondWindow);
11034
11035 // Ensure that the capture disabled event was sent first.
11036 mWindow->consumeCaptureEvent(false);
11037 mWindow->consumeFocusEvent(false);
11038 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011039 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011040
11041 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011042 notifyPointerCaptureChanged({});
11043 notifyPointerCaptureChanged(request);
11044 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011045 mWindow->assertNoEvents();
11046 mSecondWindow->assertNoEvents();
11047 mFakePolicy->assertSetPointerCaptureNotCalled();
11048}
11049
11050TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011051 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011052
11053 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011054 notifyPointerCaptureChanged({});
11055 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011056
11057 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011058 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011059 mWindow->consumeCaptureEvent(false);
11060 mWindow->assertNoEvents();
11061}
11062
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011063TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11064 requestAndVerifyPointerCapture(mWindow, true);
11065
11066 // The first window loses focus.
11067 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011068 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011069 mWindow->consumeCaptureEvent(false);
11070
11071 // Request Pointer Capture from the second window before the notification from InputReader
11072 // arrives.
11073 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011074 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011075
11076 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011077 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011078
11079 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011080 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011081
11082 mSecondWindow->consumeFocusEvent(true);
11083 mSecondWindow->consumeCaptureEvent(true);
11084}
11085
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011086TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11087 // App repeatedly enables and disables capture.
11088 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011089 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011090 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011091 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011092 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011093 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011094
11095 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11096 // first request is now stale, this should do nothing.
11097 notifyPointerCaptureChanged(firstRequest);
11098 mWindow->assertNoEvents();
11099
11100 // InputReader notifies that the second request was enabled.
11101 notifyPointerCaptureChanged(secondRequest);
11102 mWindow->consumeCaptureEvent(true);
11103}
11104
Prabir Pradhan7092e262022-05-03 16:51:09 +000011105TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11106 requestAndVerifyPointerCapture(mWindow, true);
11107
11108 // App toggles pointer capture off and on.
11109 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011110 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011111
11112 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011113 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011114
11115 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11116 // preceding "disable" request.
11117 notifyPointerCaptureChanged(enableRequest);
11118
11119 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11120 // any notifications.
11121 mWindow->assertNoEvents();
11122}
11123
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011124/**
11125 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11126 * mouse movements don't affect the previous mouse hovering state.
11127 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11128 * HOVER_MOVE events).
11129 */
11130TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11131 // Mouse hover on the window
11132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11133 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11134 .build());
11135 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11136 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11137 .build());
11138
11139 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11140 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11141
11142 // Start pointer capture
11143 requestAndVerifyPointerCapture(mWindow, true);
11144
11145 // Send some relative mouse movements and receive them in the window.
11146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11147 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11148 .build());
11149 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11150 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11151
11152 // Stop pointer capture
11153 requestAndVerifyPointerCapture(mWindow, false);
11154
11155 // Continue hovering on the window
11156 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11157 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11158 .build());
11159 mWindow->consumeMotionEvent(
11160 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11161
11162 mWindow->assertNoEvents();
11163}
11164
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011165TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11166 // The default display is the focused display to begin with.
11167 requestAndVerifyPointerCapture(mWindow, true);
11168
11169 // Move the second window to a second display, make it the focused window on that display.
11170 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11171 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11172 setFocusedWindow(mSecondWindow);
11173 mSecondWindow->consumeFocusEvent(true);
11174
11175 mWindow->assertNoEvents();
11176
11177 // The second window cannot gain capture because it is not on the focused display.
11178 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11179 mFakePolicy->assertSetPointerCaptureNotCalled();
11180 mSecondWindow->assertNoEvents();
11181
11182 // Make the second display the focused display.
11183 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011184 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011185
11186 // This causes the first window to lose pointer capture, and it's unable to request capture.
11187 mWindow->consumeCaptureEvent(false);
11188 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11189
11190 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11191 mFakePolicy->assertSetPointerCaptureNotCalled();
11192
11193 // The second window is now able to gain pointer capture successfully.
11194 requestAndVerifyPointerCapture(mSecondWindow, true);
11195}
11196
Hiroki Sato25040232024-02-22 17:21:22 +090011197using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11198
11199TEST_F(InputDispatcherPointerCaptureDeathTest,
11200 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11201 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11202 ScopedSilentDeath _silentDeath;
11203
11204 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11205 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11206
11207 // Dispatch a pointer changed event with a wrong token.
11208 request.window = mSecondWindow->getToken();
11209 ASSERT_DEATH(
11210 {
11211 notifyPointerCaptureChanged(request);
11212 mSecondWindow->consumeCaptureEvent(true);
11213 },
11214 "Unexpected requested window for Pointer Capture.");
11215}
11216
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011217class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11218protected:
11219 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011220
11221 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11222 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11223
11224 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11225 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11226
11227 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11228 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11229 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11230 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11231 MAXIMUM_OBSCURING_OPACITY);
11232
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011233 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11234 static constexpr gui::Uid APP_B_UID{10002};
11235 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011236
11237 sp<FakeWindowHandle> mTouchWindow;
11238
11239 virtual void SetUp() override {
11240 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011241 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011242 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11243 }
11244
11245 virtual void TearDown() override {
11246 InputDispatcherTest::TearDown();
11247 mTouchWindow.clear();
11248 }
11249
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011250 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011251 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011252 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011253 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011254 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011255 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011256 return window;
11257 }
11258
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011259 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011260 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11261 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011262 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011263 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011264 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011265 return window;
11266 }
11267
11268 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011269 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011270 AINPUT_SOURCE_TOUCHSCREEN,
11271 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011272 }
11273};
11274
11275TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011276 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011277 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011278 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011279
11280 touch();
11281
11282 mTouchWindow->assertNoEvents();
11283}
11284
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011285TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011286 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11287 const sp<FakeWindowHandle>& w =
11288 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011289 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011290
11291 touch();
11292
11293 mTouchWindow->assertNoEvents();
11294}
11295
11296TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011297 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11298 const sp<FakeWindowHandle>& w =
11299 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011300 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011301
11302 touch();
11303
11304 w->assertNoEvents();
11305}
11306
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011307TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011308 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011309 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011310
11311 touch();
11312
11313 mTouchWindow->consumeAnyMotionDown();
11314}
11315
11316TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011317 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011318 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011319 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011320 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011321
11322 touch({PointF{100, 100}});
11323
11324 mTouchWindow->consumeAnyMotionDown();
11325}
11326
11327TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011328 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011329 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011330 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011331
11332 touch();
11333
11334 mTouchWindow->consumeAnyMotionDown();
11335}
11336
11337TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11338 const sp<FakeWindowHandle>& w =
11339 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011340 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011341
11342 touch();
11343
11344 mTouchWindow->consumeAnyMotionDown();
11345}
11346
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011347TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11348 const sp<FakeWindowHandle>& w =
11349 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011350 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011351
11352 touch();
11353
11354 w->assertNoEvents();
11355}
11356
11357/**
11358 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11359 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11360 * window, the occluding window will still receive ACTION_OUTSIDE event.
11361 */
11362TEST_F(InputDispatcherUntrustedTouchesTest,
11363 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11364 const sp<FakeWindowHandle>& w =
11365 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011366 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011367 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011368
11369 touch();
11370
11371 w->consumeMotionOutside();
11372}
11373
11374TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11375 const sp<FakeWindowHandle>& w =
11376 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011377 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011378 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011379
11380 touch();
11381
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011382 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011383}
11384
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011385TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011386 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011387 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11388 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011389 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011390
11391 touch();
11392
11393 mTouchWindow->consumeAnyMotionDown();
11394}
11395
11396TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11397 const sp<FakeWindowHandle>& w =
11398 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11399 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011400 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011401
11402 touch();
11403
11404 mTouchWindow->consumeAnyMotionDown();
11405}
11406
11407TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011408 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011409 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11410 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011411 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011412
11413 touch();
11414
11415 mTouchWindow->assertNoEvents();
11416}
11417
11418TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11419 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11420 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011421 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11422 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011423 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011424 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11425 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011426 mDispatcher->onWindowInfosChanged(
11427 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011428
11429 touch();
11430
11431 mTouchWindow->assertNoEvents();
11432}
11433
11434TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11435 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11436 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011437 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11438 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011439 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011440 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11441 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011442 mDispatcher->onWindowInfosChanged(
11443 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011444
11445 touch();
11446
11447 mTouchWindow->consumeAnyMotionDown();
11448}
11449
11450TEST_F(InputDispatcherUntrustedTouchesTest,
11451 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11452 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011453 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11454 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011455 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011456 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11457 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011458 mDispatcher->onWindowInfosChanged(
11459 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011460
11461 touch();
11462
11463 mTouchWindow->consumeAnyMotionDown();
11464}
11465
11466TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11467 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011468 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11469 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011470 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011471 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11472 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011473 mDispatcher->onWindowInfosChanged(
11474 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011475
11476 touch();
11477
11478 mTouchWindow->assertNoEvents();
11479}
11480
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011481TEST_F(InputDispatcherUntrustedTouchesTest,
11482 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11483 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011484 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11485 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011486 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011487 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11488 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011489 mDispatcher->onWindowInfosChanged(
11490 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011491
11492 touch();
11493
11494 mTouchWindow->assertNoEvents();
11495}
11496
11497TEST_F(InputDispatcherUntrustedTouchesTest,
11498 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11499 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011500 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11501 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011502 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011503 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11504 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011505 mDispatcher->onWindowInfosChanged(
11506 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011507
11508 touch();
11509
11510 mTouchWindow->consumeAnyMotionDown();
11511}
11512
11513TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11514 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011515 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11516 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011517 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011518
11519 touch();
11520
11521 mTouchWindow->consumeAnyMotionDown();
11522}
11523
11524TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11525 const sp<FakeWindowHandle>& w =
11526 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011527 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011528
11529 touch();
11530
11531 mTouchWindow->consumeAnyMotionDown();
11532}
11533
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011534TEST_F(InputDispatcherUntrustedTouchesTest,
11535 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11536 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11537 const sp<FakeWindowHandle>& w =
11538 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011539 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011540
11541 touch();
11542
11543 mTouchWindow->assertNoEvents();
11544}
11545
11546TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11547 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11548 const sp<FakeWindowHandle>& w =
11549 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011550 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011551
11552 touch();
11553
11554 mTouchWindow->consumeAnyMotionDown();
11555}
11556
11557TEST_F(InputDispatcherUntrustedTouchesTest,
11558 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11559 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11560 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011561 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11562 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011563 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011564
11565 touch();
11566
11567 mTouchWindow->consumeAnyMotionDown();
11568}
11569
11570TEST_F(InputDispatcherUntrustedTouchesTest,
11571 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11572 const sp<FakeWindowHandle>& w1 =
11573 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11574 OPACITY_BELOW_THRESHOLD);
11575 const sp<FakeWindowHandle>& w2 =
11576 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11577 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011578 mDispatcher->onWindowInfosChanged(
11579 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011580
11581 touch();
11582
11583 mTouchWindow->assertNoEvents();
11584}
11585
11586/**
11587 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11588 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11589 * (which alone would result in allowing touches) does not affect the blocking behavior.
11590 */
11591TEST_F(InputDispatcherUntrustedTouchesTest,
11592 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11593 const sp<FakeWindowHandle>& wB =
11594 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11595 OPACITY_BELOW_THRESHOLD);
11596 const sp<FakeWindowHandle>& wC =
11597 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11598 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011599 mDispatcher->onWindowInfosChanged(
11600 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011601
11602 touch();
11603
11604 mTouchWindow->assertNoEvents();
11605}
11606
11607/**
11608 * This test is testing that a window from a different UID but with same application token doesn't
11609 * block the touch. Apps can share the application token for close UI collaboration for example.
11610 */
11611TEST_F(InputDispatcherUntrustedTouchesTest,
11612 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11613 const sp<FakeWindowHandle>& w =
11614 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11615 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011616 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011617
11618 touch();
11619
11620 mTouchWindow->consumeAnyMotionDown();
11621}
11622
arthurhungb89ccb02020-12-30 16:19:01 +080011623class InputDispatcherDragTests : public InputDispatcherTest {
11624protected:
11625 std::shared_ptr<FakeApplicationHandle> mApp;
11626 sp<FakeWindowHandle> mWindow;
11627 sp<FakeWindowHandle> mSecondWindow;
11628 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011629 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011630 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11631 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011632
11633 void SetUp() override {
11634 InputDispatcherTest::SetUp();
11635 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011636 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11637 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011638 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011639
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011640 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11641 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011642 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011643
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011644 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11645 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011646 mSpyWindow->setSpy(true);
11647 mSpyWindow->setTrustedOverlay(true);
11648 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11649
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011650 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011651 mDispatcher->onWindowInfosChanged(
11652 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11653 {},
11654 0,
11655 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011656 }
11657
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011658 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11659 switch (fromSource) {
11660 case AINPUT_SOURCE_TOUCHSCREEN:
11661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011662 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011663 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11665 break;
11666 case AINPUT_SOURCE_STYLUS:
11667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011668 injectMotionEvent(*mDispatcher,
11669 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11670 AINPUT_SOURCE_STYLUS)
11671 .buttonState(
11672 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11673 .pointer(PointerBuilder(0, ToolType::STYLUS)
11674 .x(50)
11675 .y(50))
11676 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011677 break;
11678 case AINPUT_SOURCE_MOUSE:
11679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011680 injectMotionEvent(*mDispatcher,
11681 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11682 AINPUT_SOURCE_MOUSE)
11683 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11684 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11685 ToolType::MOUSE)
11686 .x(50)
11687 .y(50))
11688 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011689 break;
11690 default:
11691 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11692 }
arthurhungb89ccb02020-12-30 16:19:01 +080011693
11694 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011695 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011696 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011697 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011698 }
11699
11700 // Start performing drag, we will create a drag window and transfer touch to it.
11701 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11702 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011703 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011704 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011705 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011706 }
arthurhungb89ccb02020-12-30 16:19:01 +080011707
11708 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011709 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11710 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011711 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011712 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11713 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11714 {},
11715 0,
11716 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011717
11718 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011719 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011720 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11721 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011722 if (transferred) {
11723 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011724 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11725 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011726 }
11727 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011728 }
11729};
11730
11731TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011732 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011733
11734 // Move on window.
11735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011736 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011737 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011739 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11740 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011741 mWindow->consumeDragEvent(false, 50, 50);
11742 mSecondWindow->assertNoEvents();
11743
11744 // Move to another window.
11745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011746 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011747 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011749 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11750 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011751 mWindow->consumeDragEvent(true, 150, 50);
11752 mSecondWindow->consumeDragEvent(false, 50, 50);
11753
11754 // Move back to original window.
11755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011756 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011757 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011759 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11760 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011761 mWindow->consumeDragEvent(false, 50, 50);
11762 mSecondWindow->consumeDragEvent(true, -50, 50);
11763
11764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011765 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011766 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011768 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011769 mWindow->assertNoEvents();
11770 mSecondWindow->assertNoEvents();
11771}
11772
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011773TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011774 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011775
11776 // No cancel event after drag start
11777 mSpyWindow->assertNoEvents();
11778
11779 const MotionEvent secondFingerDownEvent =
11780 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11781 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011782 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11783 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011784 .build();
11785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011786 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011787 InputEventInjectionSync::WAIT_FOR_RESULT))
11788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11789
11790 // Receives cancel for first pointer after next pointer down
11791 mSpyWindow->consumeMotionCancel();
11792 mSpyWindow->consumeMotionDown();
11793
11794 mSpyWindow->assertNoEvents();
11795}
11796
arthurhungf452d0b2021-01-06 00:19:52 +080011797TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011798 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080011799
11800 // Move on window.
11801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011802 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011803 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011805 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11806 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011807 mWindow->consumeDragEvent(false, 50, 50);
11808 mSecondWindow->assertNoEvents();
11809
11810 // Move to another window.
11811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011812 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011813 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011815 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11816 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011817 mWindow->consumeDragEvent(true, 150, 50);
11818 mSecondWindow->consumeDragEvent(false, 50, 50);
11819
11820 // drop to another window.
11821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011822 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080011823 {150, 50}))
11824 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011825 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011826 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080011827 mWindow->assertNoEvents();
11828 mSecondWindow->assertNoEvents();
11829}
11830
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011831TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
11832 startDrag();
11833
11834 // No cancel event after drag start
11835 mSpyWindow->assertNoEvents();
11836
11837 const MotionEvent secondFingerDownEvent =
11838 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11839 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11840 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11841 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11842 .build();
11843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11844 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11845 InputEventInjectionSync::WAIT_FOR_RESULT))
11846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11847
11848 // Receives cancel for first pointer after next pointer down
11849 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080011850 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011851 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
11852
11853 mSpyWindow->assertNoEvents();
11854
11855 // Spy window calls pilfer pointers
11856 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
11857 mDragWindow->assertNoEvents();
11858
11859 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011860 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011861 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11862 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
11863 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11864 .build();
11865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011866 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011867 InputEventInjectionSync::WAIT_FOR_RESULT))
11868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11869
11870 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000011871 mDragWindow->consumeMotionEvent(
11872 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011873 mDragWindow->assertNoEvents();
11874}
11875
arthurhung6d4bed92021-03-17 11:59:33 +080011876TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011877 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080011878
11879 // Move on window and keep button pressed.
11880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011881 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011882 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11883 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011884 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011885 .build()))
11886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011887 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11888 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011889 mWindow->consumeDragEvent(false, 50, 50);
11890 mSecondWindow->assertNoEvents();
11891
11892 // Move to another window and release button, expect to drop item.
11893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011894 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011895 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11896 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011897 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011898 .build()))
11899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011900 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11901 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011902 mWindow->assertNoEvents();
11903 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011904 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080011905
11906 // nothing to the window.
11907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011908 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011909 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
11910 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011911 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011912 .build()))
11913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011914 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011915 mWindow->assertNoEvents();
11916 mSecondWindow->assertNoEvents();
11917}
11918
Arthur Hung54745652022-04-20 07:17:41 +000011919TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011920 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080011921
11922 // Set second window invisible.
11923 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011924 mDispatcher->onWindowInfosChanged(
11925 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080011926
11927 // Move on window.
11928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011929 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011930 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011932 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11933 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011934 mWindow->consumeDragEvent(false, 50, 50);
11935 mSecondWindow->assertNoEvents();
11936
11937 // Move to another window.
11938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011939 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011940 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011942 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11943 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011944 mWindow->consumeDragEvent(true, 150, 50);
11945 mSecondWindow->assertNoEvents();
11946
11947 // drop to another window.
11948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011949 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080011950 {150, 50}))
11951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011952 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011953 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011954 mWindow->assertNoEvents();
11955 mSecondWindow->assertNoEvents();
11956}
11957
Arthur Hung54745652022-04-20 07:17:41 +000011958TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011959 // Ensure window could track pointerIds if it didn't support split touch.
11960 mWindow->setPreventSplitting(true);
11961
Arthur Hung54745652022-04-20 07:17:41 +000011962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011963 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11964 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011966 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011967
11968 const MotionEvent secondFingerDownEvent =
11969 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011970 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011971 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011972 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11973 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011974 .build();
11975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011976 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011977 InputEventInjectionSync::WAIT_FOR_RESULT))
11978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011979 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000011980
11981 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011982 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011983}
11984
11985TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
11986 // First down on second window.
11987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011988 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11989 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11991
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011992 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011993
11994 // Second down on first window.
11995 const MotionEvent secondFingerDownEvent =
11996 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011997 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011998 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011999 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12000 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012001 .build();
12002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012003 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012004 InputEventInjectionSync::WAIT_FOR_RESULT))
12005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012006 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12007 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012008
12009 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012010 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012011
12012 // Move on window.
12013 const MotionEvent secondFingerMoveEvent =
12014 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12015 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012016 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12017 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012018 .build();
12019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012020 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012021 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012022 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12023 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012024 mWindow->consumeDragEvent(false, 50, 50);
12025 mSecondWindow->consumeMotionMove();
12026
12027 // Release the drag pointer should perform drop.
12028 const MotionEvent secondFingerUpEvent =
12029 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12030 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012031 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12032 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012033 .build();
12034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012035 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012036 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012037 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012038 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012039 mWindow->assertNoEvents();
12040 mSecondWindow->consumeMotionMove();
12041}
12042
Arthur Hung3915c1f2022-05-31 07:17:17 +000012043TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012044 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012045
12046 // Update window of second display.
12047 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012048 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012049 mDispatcher->onWindowInfosChanged(
12050 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12051 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12052 {},
12053 0,
12054 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012055
12056 // Let second display has a touch state.
12057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012058 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012059 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12060 AINPUT_SOURCE_TOUCHSCREEN)
12061 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012062 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012063 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012064 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012065 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012066 mDispatcher->onWindowInfosChanged(
12067 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12068 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12069 {},
12070 0,
12071 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012072
12073 // Move on window.
12074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012075 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012076 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012078 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12079 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012080 mWindow->consumeDragEvent(false, 50, 50);
12081 mSecondWindow->assertNoEvents();
12082
12083 // Move to another window.
12084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012085 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012086 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012088 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12089 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012090 mWindow->consumeDragEvent(true, 150, 50);
12091 mSecondWindow->consumeDragEvent(false, 50, 50);
12092
12093 // drop to another window.
12094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012095 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012096 {150, 50}))
12097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012098 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012099 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012100 mWindow->assertNoEvents();
12101 mSecondWindow->assertNoEvents();
12102}
12103
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012104TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12105 startDrag(true, AINPUT_SOURCE_MOUSE);
12106 // Move on window.
12107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012108 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012109 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12110 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012111 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012112 .x(50)
12113 .y(50))
12114 .build()))
12115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012116 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12117 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012118 mWindow->consumeDragEvent(false, 50, 50);
12119 mSecondWindow->assertNoEvents();
12120
12121 // Move to another window.
12122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012123 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012124 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12125 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012126 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012127 .x(150)
12128 .y(50))
12129 .build()))
12130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012131 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12132 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012133 mWindow->consumeDragEvent(true, 150, 50);
12134 mSecondWindow->consumeDragEvent(false, 50, 50);
12135
12136 // drop to another window.
12137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012138 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012139 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12140 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012141 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012142 .x(150)
12143 .y(50))
12144 .build()))
12145 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012146 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012147 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012148 mWindow->assertNoEvents();
12149 mSecondWindow->assertNoEvents();
12150}
12151
Linnan Li5af92f92023-07-14 14:36:22 +080012152/**
12153 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12154 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12155 */
12156TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12157 // Down on second window
12158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012159 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12160 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12162
12163 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12164 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12165
12166 // Down on first window
12167 const MotionEvent secondFingerDownEvent =
12168 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012169 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012170 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12171 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12172 .build();
12173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12174 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12175 InputEventInjectionSync::WAIT_FOR_RESULT))
12176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12177 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12178 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12179 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12180
12181 // Start drag on first window
12182 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12183
12184 // Trigger cancel
12185 mDispatcher->cancelCurrentTouch();
12186 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012187 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012188 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012189 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12190
12191 ASSERT_TRUE(mDispatcher->waitForIdle());
12192 // The D&D finished with nullptr
12193 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12194
12195 // Remove drag window
12196 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12197
12198 // Inject a simple gesture, ensure dispatcher not crashed
12199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012200 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12201 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012202 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12203 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12204
12205 const MotionEvent moveEvent =
12206 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012207 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012208 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12209 .build();
12210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12211 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12212 InputEventInjectionSync::WAIT_FOR_RESULT))
12213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12214 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12215
12216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012217 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012218 {50, 50}))
12219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12220 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12221}
12222
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012223TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12224 // Start hovering over the window.
12225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12226 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012227 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012228
12229 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12230 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12231
12232 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12233 << "Drag and drop should not work with a hovering pointer";
12234}
12235
Vishnu Nair062a8672021-09-03 16:07:44 -070012236class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12237
12238TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12239 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012240 sp<FakeWindowHandle> window =
12241 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12242 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012243 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012244 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012245 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012246 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012247 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012248 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012249
12250 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012251 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012252 window->assertNoEvents();
12253
Prabir Pradhan678438e2023-04-13 19:32:51 +000012254 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012255 AINPUT_SOURCE_TOUCHSCREEN,
12256 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012257 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012258 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012259 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012260 window->assertNoEvents();
12261
12262 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012263 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012264 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012265
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012266 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12267 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012268
Prabir Pradhan678438e2023-04-13 19:32:51 +000012269 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012270 AINPUT_SOURCE_TOUCHSCREEN,
12271 ui::LogicalDisplayId::DEFAULT));
12272 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012273 window->assertNoEvents();
12274}
12275
12276TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12277 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12278 std::make_shared<FakeApplicationHandle>();
12279 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012280 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012281 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012282 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012283 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012284 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012286 sp<FakeWindowHandle> window =
12287 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12288 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012289 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012290 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012291 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012292 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012293 mDispatcher->onWindowInfosChanged(
12294 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012295 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012296 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012297
12298 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012299 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012300 window->assertNoEvents();
12301
Prabir Pradhan678438e2023-04-13 19:32:51 +000012302 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012303 AINPUT_SOURCE_TOUCHSCREEN,
12304 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012305 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012306 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012307 window->assertNoEvents();
12308
12309 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012310 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012311 mDispatcher->onWindowInfosChanged(
12312 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012313
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012314 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12315 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012316
Prabir Pradhan678438e2023-04-13 19:32:51 +000012317 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012318 AINPUT_SOURCE_TOUCHSCREEN,
12319 ui::LogicalDisplayId::DEFAULT));
12320 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12321 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012322 window->assertNoEvents();
12323}
12324
12325TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12326 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12327 std::make_shared<FakeApplicationHandle>();
12328 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012329 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012330 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012331 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012332 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012333 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012334 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012335 sp<FakeWindowHandle> window =
12336 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12337 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012338 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012339 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012340 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012341 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012342 mDispatcher->onWindowInfosChanged(
12343 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012344 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012345 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012346
12347 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012348 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012349 window->assertNoEvents();
12350
Prabir Pradhan678438e2023-04-13 19:32:51 +000012351 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012352 AINPUT_SOURCE_TOUCHSCREEN,
12353 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012354 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012355 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012356 window->assertNoEvents();
12357
12358 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012359 mDispatcher->onWindowInfosChanged(
12360 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012361
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012362 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12363 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012364
Prabir Pradhan678438e2023-04-13 19:32:51 +000012365 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012366 AINPUT_SOURCE_TOUCHSCREEN,
12367 ui::LogicalDisplayId::DEFAULT));
12368 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012369 window->assertNoEvents();
12370}
12371
Antonio Kantekf16f2832021-09-28 04:39:20 +000012372class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12373protected:
12374 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012375 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012376 sp<FakeWindowHandle> mWindow;
12377 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012378 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012379
12380 void SetUp() override {
12381 InputDispatcherTest::SetUp();
12382
12383 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012384 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012385 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12386 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012387 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012388 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012389 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12390 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012391 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012392 mThirdWindow =
12393 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12394 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12395 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012396
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012397 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012398 mDispatcher->onWindowInfosChanged(
12399 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12400 {},
12401 0,
12402 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012403 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012404 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012405
Antonio Kantek15beb512022-06-13 22:35:41 +000012406 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012407 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012408 WINDOW_UID, /*hasPermission=*/true,
12409 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012410 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12411 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012412 mThirdWindow->assertNoEvents();
12413 }
12414
12415 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12416 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012417 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012418 SECOND_DISPLAY_ID)) {
12419 mWindow->assertNoEvents();
12420 mSecondWindow->assertNoEvents();
12421 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012422 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012423 }
12424
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012425 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012426 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012427 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012428 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012429 mWindow->consumeTouchModeEvent(inTouchMode);
12430 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012431 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012432 }
12433};
12434
Antonio Kantek26defcf2022-02-08 01:12:27 +000012435TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012436 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012437 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12438 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012439 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012440}
12441
Antonio Kantek26defcf2022-02-08 01:12:27 +000012442TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12443 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012444 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012445 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012446 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012447 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012448 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012449 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012450 mWindow->assertNoEvents();
12451 mSecondWindow->assertNoEvents();
12452}
12453
12454TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12455 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012456 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012457 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012458 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012459 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012460 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012461}
12462
Antonio Kantekf16f2832021-09-28 04:39:20 +000012463TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012464 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012465 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12466 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012467 /*hasPermission=*/true,
12468 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012469 mWindow->assertNoEvents();
12470 mSecondWindow->assertNoEvents();
12471}
12472
Antonio Kantek15beb512022-06-13 22:35:41 +000012473TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12474 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12475 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12476 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012477 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012478 mWindow->assertNoEvents();
12479 mSecondWindow->assertNoEvents();
12480 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12481}
12482
Antonio Kantek48710e42022-03-24 14:19:30 -070012483TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12484 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012486 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012487 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012488 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012489
12490 // Then remove focus.
12491 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012492 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012493
12494 // Assert that caller can switch touch mode by owning one of the last interacted window.
12495 const WindowInfo& windowInfo = *mWindow->getInfo();
12496 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12497 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012498 /*hasPermission=*/false,
12499 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012500}
12501
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012502class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12503public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012504 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012505 std::shared_ptr<FakeApplicationHandle> application =
12506 std::make_shared<FakeApplicationHandle>();
12507 std::string name = "Fake Spy ";
12508 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012509 sp<FakeWindowHandle> spy =
12510 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12511 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012512 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012513 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012514 return spy;
12515 }
12516
12517 sp<FakeWindowHandle> createForeground() {
12518 std::shared_ptr<FakeApplicationHandle> application =
12519 std::make_shared<FakeApplicationHandle>();
12520 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012521 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012522 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012523 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012524 return window;
12525 }
12526
12527private:
12528 int mSpyCount{0};
12529};
12530
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012531using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012532/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012533 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12534 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012535TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012536 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012537 ScopedSilentDeath _silentDeath;
12538
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012539 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012540 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012541 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012542 ".* not a trusted overlay");
12543}
12544
12545/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012546 * Input injection into a display with a spy window but no foreground windows should succeed.
12547 */
12548TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012549 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012550 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012551
12552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012553 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12554 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012556 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012557}
12558
12559/**
12560 * Verify the order in which different input windows receive events. The touched foreground window
12561 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12562 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12563 * receive events before ones belows it.
12564 *
12565 * Here, we set up a scenario with four windows in the following Z order from the top:
12566 * spy1, spy2, window, spy3.
12567 * We then inject an event and verify that the foreground "window" receives it first, followed by
12568 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12569 * window.
12570 */
12571TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12572 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012573 auto spy1 = createSpy();
12574 auto spy2 = createSpy();
12575 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012576 mDispatcher->onWindowInfosChanged(
12577 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012578 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12579 const size_t numChannels = channels.size();
12580
Michael Wright8e9a8562022-02-09 13:44:29 +000012581 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012582 if (!epollFd.ok()) {
12583 FAIL() << "Failed to create epoll fd";
12584 }
12585
12586 for (size_t i = 0; i < numChannels; i++) {
12587 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12588 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12589 FAIL() << "Failed to add fd to epoll";
12590 }
12591 }
12592
12593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012594 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12595 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12597
12598 std::vector<size_t> eventOrder;
12599 std::vector<struct epoll_event> events(numChannels);
12600 for (;;) {
12601 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12602 (100ms).count());
12603 if (nFds < 0) {
12604 FAIL() << "Failed to call epoll_wait";
12605 }
12606 if (nFds == 0) {
12607 break; // epoll_wait timed out
12608 }
12609 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012610 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012611 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012612 channels[i]->consumeMotionDown();
12613 }
12614 }
12615
12616 // Verify the order in which the events were received.
12617 EXPECT_EQ(3u, eventOrder.size());
12618 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12619 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12620 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12621}
12622
12623/**
12624 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12625 */
12626TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12627 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012628 auto spy = createSpy();
12629 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012630 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012631
12632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012633 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12634 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012636 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012637 spy->assertNoEvents();
12638}
12639
12640/**
12641 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12642 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12643 * to the window.
12644 */
12645TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12646 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012647 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012648 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012649 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012650
12651 // Inject an event outside the spy window's touchable region.
12652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012653 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12654 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12656 window->consumeMotionDown();
12657 spy->assertNoEvents();
12658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012659 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12660 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12662 window->consumeMotionUp();
12663 spy->assertNoEvents();
12664
12665 // Inject an event inside the spy window's touchable region.
12666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012667 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12668 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12670 window->consumeMotionDown();
12671 spy->consumeMotionDown();
12672}
12673
12674/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012675 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012676 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012677 */
12678TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12679 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012680 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012681 auto spy = createSpy();
12682 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012683 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012684 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012685 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012686
12687 // Inject an event outside the spy window's frame and touchable region.
12688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012689 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12690 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12692 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012693 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012694}
12695
12696/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012697 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12698 * pointers that are down within its bounds.
12699 */
12700TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12701 auto windowLeft = createForeground();
12702 windowLeft->setFrame({0, 0, 100, 200});
12703 auto windowRight = createForeground();
12704 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012705 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012706 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012707 mDispatcher->onWindowInfosChanged(
12708 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012709
12710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12712 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12714 windowLeft->consumeMotionDown();
12715 spy->consumeMotionDown();
12716
12717 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012718 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012719 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012720 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12721 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012722 .build();
12723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012724 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012725 InputEventInjectionSync::WAIT_FOR_RESULT))
12726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12727 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012728 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012729}
12730
12731/**
12732 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12733 * the spy should receive the second pointer with ACTION_DOWN.
12734 */
12735TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12736 auto window = createForeground();
12737 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012738 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012739 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012740 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012741
12742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012743 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12744 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012745 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12746 window->consumeMotionDown();
12747 spyRight->assertNoEvents();
12748
12749 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012750 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012751 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012752 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12753 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012754 .build();
12755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012756 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012757 InputEventInjectionSync::WAIT_FOR_RESULT))
12758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012759 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012760 spyRight->consumeMotionDown();
12761}
12762
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012763/**
12764 * The spy window should not be able to affect whether or not touches are split. Only the foreground
12765 * windows should be allowed to control split touch.
12766 */
12767TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012768 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012769 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012770 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012771 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012772
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012773 auto window = createForeground();
12774 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012775
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012776 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012777
12778 // First finger down, no window touched.
12779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12781 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012783 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012784 window->assertNoEvents();
12785
12786 // Second finger down on window, the window should receive touch down.
12787 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012788 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012789 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012790 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012791 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12792 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012793 .build();
12794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012795 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012796 InputEventInjectionSync::WAIT_FOR_RESULT))
12797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12798
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012799 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000012800 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012801}
12802
12803/**
12804 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
12805 * do not receive key events.
12806 */
12807TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012808 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012809 spy->setFocusable(false);
12810
12811 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012812 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012813 setFocusedWindow(window);
12814 window->consumeFocusEvent(true);
12815
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012817 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012818 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012819
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012821 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012822 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012823
12824 spy->assertNoEvents();
12825}
12826
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012827using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
12828
12829/**
12830 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
12831 * are currently sent to any other windows - including other spy windows - will also be cancelled.
12832 */
12833TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
12834 auto window = createForeground();
12835 auto spy1 = createSpy();
12836 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012837 mDispatcher->onWindowInfosChanged(
12838 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012839
12840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012841 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12842 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12844 window->consumeMotionDown();
12845 spy1->consumeMotionDown();
12846 spy2->consumeMotionDown();
12847
12848 // Pilfer pointers from the second spy window.
12849 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
12850 spy2->assertNoEvents();
12851 spy1->consumeMotionCancel();
12852 window->consumeMotionCancel();
12853
12854 // The rest of the gesture should only be sent to the second spy window.
12855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012856 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012857 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12859 spy2->consumeMotionMove();
12860 spy1->assertNoEvents();
12861 window->assertNoEvents();
12862}
12863
12864/**
12865 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
12866 * in the middle of the gesture.
12867 */
12868TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
12869 auto window = createForeground();
12870 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012871 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012872
12873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012874 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12875 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012877 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12878 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012879
12880 window->releaseChannel();
12881
12882 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12883
12884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012885 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12886 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012888 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012889}
12890
12891/**
12892 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
12893 * the spy, but not to any other windows.
12894 */
12895TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
12896 auto spy = createSpy();
12897 auto window = createForeground();
12898
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012899 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012900
12901 // First finger down on the window and the spy.
12902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012903 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12904 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12906 spy->consumeMotionDown();
12907 window->consumeMotionDown();
12908
12909 // Spy window pilfers the pointers.
12910 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12911 window->consumeMotionCancel();
12912
12913 // Second finger down on the window and spy, but the window should not receive the pointer down.
12914 const MotionEvent secondFingerDownEvent =
12915 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012916 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012917 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012918 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12919 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012920 .build();
12921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012922 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012923 InputEventInjectionSync::WAIT_FOR_RESULT))
12924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12925
Harry Cutts33476232023-01-30 19:57:29 +000012926 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012927
12928 // Third finger goes down outside all windows, so injection should fail.
12929 const MotionEvent thirdFingerDownEvent =
12930 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012931 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012932 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012933 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12934 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12935 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012936 .build();
12937 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012938 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012939 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080012940 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012941
12942 spy->assertNoEvents();
12943 window->assertNoEvents();
12944}
12945
12946/**
12947 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
12948 */
12949TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
12950 auto spy = createSpy();
12951 spy->setFrame(Rect(0, 0, 100, 100));
12952 auto window = createForeground();
12953 window->setFrame(Rect(0, 0, 200, 200));
12954
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012955 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012956
12957 // First finger down on the window only
12958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012959 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12960 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12962 window->consumeMotionDown();
12963
12964 // Second finger down on the spy and window
12965 const MotionEvent secondFingerDownEvent =
12966 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012967 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012968 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012969 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
12970 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012971 .build();
12972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012973 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012974 InputEventInjectionSync::WAIT_FOR_RESULT))
12975 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12976 spy->consumeMotionDown();
12977 window->consumeMotionPointerDown(1);
12978
12979 // Third finger down on the spy and window
12980 const MotionEvent thirdFingerDownEvent =
12981 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012982 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012983 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012984 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
12985 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
12986 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012987 .build();
12988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012989 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012990 InputEventInjectionSync::WAIT_FOR_RESULT))
12991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12992 spy->consumeMotionPointerDown(1);
12993 window->consumeMotionPointerDown(2);
12994
12995 // Spy window pilfers the pointers.
12996 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000012997 window->consumeMotionPointerUp(/*pointerIdx=*/2,
12998 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12999 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13000 WithPointerCount(3)));
13001 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13002 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13003 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13004 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013005
13006 spy->assertNoEvents();
13007 window->assertNoEvents();
13008}
13009
13010/**
13011 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13012 * other windows should be canceled. If this results in the cancellation of all pointers for some
13013 * window, then that window should receive ACTION_CANCEL.
13014 */
13015TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13016 auto spy = createSpy();
13017 spy->setFrame(Rect(0, 0, 100, 100));
13018 auto window = createForeground();
13019 window->setFrame(Rect(0, 0, 200, 200));
13020
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013021 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013022
13023 // First finger down on both spy and window
13024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013025 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13026 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13028 window->consumeMotionDown();
13029 spy->consumeMotionDown();
13030
13031 // Second finger down on the spy and window
13032 const MotionEvent secondFingerDownEvent =
13033 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013034 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013038 .build();
13039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013040 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013041 InputEventInjectionSync::WAIT_FOR_RESULT))
13042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13043 spy->consumeMotionPointerDown(1);
13044 window->consumeMotionPointerDown(1);
13045
13046 // Spy window pilfers the pointers.
13047 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13048 window->consumeMotionCancel();
13049
13050 spy->assertNoEvents();
13051 window->assertNoEvents();
13052}
13053
13054/**
13055 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13056 * be sent to other windows
13057 */
13058TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13059 auto spy = createSpy();
13060 spy->setFrame(Rect(0, 0, 100, 100));
13061 auto window = createForeground();
13062 window->setFrame(Rect(0, 0, 200, 200));
13063
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013064 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013065
13066 // First finger down on both window and spy
13067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013068 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13069 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13071 window->consumeMotionDown();
13072 spy->consumeMotionDown();
13073
13074 // Spy window pilfers the pointers.
13075 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13076 window->consumeMotionCancel();
13077
13078 // Second finger down on the window only
13079 const MotionEvent secondFingerDownEvent =
13080 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013081 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013082 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013083 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13084 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013085 .build();
13086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013087 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013088 InputEventInjectionSync::WAIT_FOR_RESULT))
13089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13090 window->consumeMotionDown();
13091 window->assertNoEvents();
13092
13093 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13094 spy->consumeMotionMove();
13095 spy->assertNoEvents();
13096}
13097
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013098/**
13099 * A window on the left and a window on the right. Also, a spy window that's above all of the
13100 * windows, and spanning both left and right windows.
13101 * Send simultaneous motion streams from two different devices, one to the left window, and another
13102 * to the right window.
13103 * Pilfer from spy window.
13104 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13105 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013106TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13107 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013108 sp<FakeWindowHandle> spy = createSpy();
13109 spy->setFrame(Rect(0, 0, 200, 200));
13110 sp<FakeWindowHandle> leftWindow = createForeground();
13111 leftWindow->setFrame(Rect(0, 0, 100, 100));
13112
13113 sp<FakeWindowHandle> rightWindow = createForeground();
13114 rightWindow->setFrame(Rect(100, 0, 200, 100));
13115
13116 constexpr int32_t stylusDeviceId = 1;
13117 constexpr int32_t touchDeviceId = 2;
13118
13119 mDispatcher->onWindowInfosChanged(
13120 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13121
13122 // Stylus down on left window and spy
13123 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13124 .deviceId(stylusDeviceId)
13125 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13126 .build());
13127 leftWindow->consumeMotionEvent(
13128 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13129 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13130
13131 // Finger down on right window and spy - but spy already has stylus
13132 mDispatcher->notifyMotion(
13133 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13134 .deviceId(touchDeviceId)
13135 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13136 .build());
13137 rightWindow->consumeMotionEvent(
13138 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013139 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013140
13141 // Act: pilfer from spy. Spy is currently receiving touch events.
13142 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013143 leftWindow->consumeMotionEvent(
13144 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013145 rightWindow->consumeMotionEvent(
13146 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13147
13148 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13149 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13150 .deviceId(stylusDeviceId)
13151 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13152 .build());
13153 mDispatcher->notifyMotion(
13154 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13155 .deviceId(touchDeviceId)
13156 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13157 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013158 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013159
13160 spy->assertNoEvents();
13161 leftWindow->assertNoEvents();
13162 rightWindow->assertNoEvents();
13163}
13164
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013165/**
13166 * A window on the left and a window on the right. Also, a spy window that's above all of the
13167 * windows, and spanning both left and right windows.
13168 * Send simultaneous motion streams from two different devices, one to the left window, and another
13169 * to the right window.
13170 * Pilfer from spy window.
13171 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13172 * The spy should receive both the touch and the stylus events after pilfer.
13173 */
13174TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13175 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13176 sp<FakeWindowHandle> spy = createSpy();
13177 spy->setFrame(Rect(0, 0, 200, 200));
13178 sp<FakeWindowHandle> leftWindow = createForeground();
13179 leftWindow->setFrame(Rect(0, 0, 100, 100));
13180
13181 sp<FakeWindowHandle> rightWindow = createForeground();
13182 rightWindow->setFrame(Rect(100, 0, 200, 100));
13183
13184 constexpr int32_t stylusDeviceId = 1;
13185 constexpr int32_t touchDeviceId = 2;
13186
13187 mDispatcher->onWindowInfosChanged(
13188 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13189
13190 // Stylus down on left window and spy
13191 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13192 .deviceId(stylusDeviceId)
13193 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13194 .build());
13195 leftWindow->consumeMotionEvent(
13196 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13197 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13198
13199 // Finger down on right window and spy
13200 mDispatcher->notifyMotion(
13201 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13202 .deviceId(touchDeviceId)
13203 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13204 .build());
13205 rightWindow->consumeMotionEvent(
13206 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13207 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13208
13209 // Act: pilfer from spy. Spy is currently receiving touch events.
13210 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13211 leftWindow->consumeMotionEvent(
13212 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13213 rightWindow->consumeMotionEvent(
13214 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13215
13216 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013217 // Instead of sending the two MOVE events for each input device together, and then receiving
13218 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13219 // means that the two MOVE events will be initially put into a batch. Once the events are
13220 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13221 // on the implementation of InputConsumer), which would mean that the order of the received
13222 // events could be different depending on whether there are 1 or 2 events pending in the
13223 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13224 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013225 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13226 .deviceId(stylusDeviceId)
13227 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13228 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013229 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013230 mDispatcher->notifyMotion(
13231 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13232 .deviceId(touchDeviceId)
13233 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13234 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013235 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013236
13237 spy->assertNoEvents();
13238 leftWindow->assertNoEvents();
13239 rightWindow->assertNoEvents();
13240}
13241
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013242TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13243 auto window = createForeground();
13244 auto spy = createSpy();
13245 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13246
13247 mDispatcher->notifyMotion(
13248 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13249 .deviceId(1)
13250 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13251 .build());
13252 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13253 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13254
13255 // Pilfer pointers from the spy window should fail.
13256 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13257 spy->assertNoEvents();
13258 window->assertNoEvents();
13259}
13260
Prabir Pradhand65552b2021-10-07 11:23:50 -070013261class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13262public:
13263 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13264 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13265 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013266 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13267 "Stylus interceptor window",
13268 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013269 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013270 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013271 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013272 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013273 overlay->setTrustedOverlay(true);
13274
13275 std::shared_ptr<FakeApplicationHandle> application =
13276 std::make_shared<FakeApplicationHandle>();
13277 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013278 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013279 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013280 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013281 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013282
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013283 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013284 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013285 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013286 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013287 return {std::move(overlay), std::move(window)};
13288 }
13289
13290 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013291 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013292 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013293 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013294 }
13295
13296 void sendStylusEvent(int32_t action) {
13297 NotifyMotionArgs motionArgs =
13298 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013299 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013300 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013301 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013302 }
13303};
13304
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013305using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13306
13307TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013308 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013309 ScopedSilentDeath _silentDeath;
13310
Prabir Pradhand65552b2021-10-07 11:23:50 -070013311 auto [overlay, window] = setupStylusOverlayScenario();
13312 overlay->setTrustedOverlay(false);
13313 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013314 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13315 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013316 ".* not a trusted overlay");
13317}
13318
13319TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13320 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013321 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013322
13323 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13324 overlay->consumeMotionDown();
13325 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13326 overlay->consumeMotionUp();
13327
13328 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13329 window->consumeMotionDown();
13330 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13331 window->consumeMotionUp();
13332
13333 overlay->assertNoEvents();
13334 window->assertNoEvents();
13335}
13336
13337TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13338 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013339 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013340 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013341
13342 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13343 overlay->consumeMotionDown();
13344 window->consumeMotionDown();
13345 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13346 overlay->consumeMotionUp();
13347 window->consumeMotionUp();
13348
13349 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13350 window->consumeMotionDown();
13351 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13352 window->consumeMotionUp();
13353
13354 overlay->assertNoEvents();
13355 window->assertNoEvents();
13356}
13357
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013358/**
13359 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13360 * The scenario is as follows:
13361 * - The stylus interceptor overlay is configured as a spy window.
13362 * - The stylus interceptor spy receives the start of a new stylus gesture.
13363 * - It pilfers pointers and then configures itself to no longer be a spy.
13364 * - The stylus interceptor continues to receive the rest of the gesture.
13365 */
13366TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13367 auto [overlay, window] = setupStylusOverlayScenario();
13368 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013369 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013370
13371 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13372 overlay->consumeMotionDown();
13373 window->consumeMotionDown();
13374
13375 // The interceptor pilfers the pointers.
13376 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13377 window->consumeMotionCancel();
13378
13379 // The interceptor configures itself so that it is no longer a spy.
13380 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013381 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013382
13383 // It continues to receive the rest of the stylus gesture.
13384 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13385 overlay->consumeMotionMove();
13386 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13387 overlay->consumeMotionUp();
13388
13389 window->assertNoEvents();
13390}
13391
Prabir Pradhan5735a322022-04-11 17:23:34 +000013392struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013393 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013394 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013395 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13396 std::unique_ptr<InputDispatcher>& mDispatcher;
13397
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013398 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013399 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13400
13401 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013402 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013403 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013404 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13405 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13406 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13407 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13408 }
13409
13410 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013411 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013412 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013413 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013414 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013415 mPolicyFlags);
13416 }
13417
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013418 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013419 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13420 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013421 sp<FakeWindowHandle> window =
13422 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13423 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013424 window->setOwnerInfo(mPid, mUid);
13425 return window;
13426 }
13427};
13428
13429using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13430
13431TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013432 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013433 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013434 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013435
13436 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13437 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13438 window->consumeMotionDown();
13439
13440 setFocusedWindow(window);
13441 window->consumeFocusEvent(true);
13442
13443 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13444 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013445 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013446}
13447
13448TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013449 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013450 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013451 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013452
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013453 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013454 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13455 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13456
13457 setFocusedWindow(window);
13458 window->consumeFocusEvent(true);
13459
13460 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13461 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13462 window->assertNoEvents();
13463}
13464
13465TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013466 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013467 auto window = owner.createWindow("Owned window");
13468 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013469 spy->setSpy(true);
13470 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013471 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013472
13473 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13474 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13475 spy->consumeMotionDown();
13476 window->consumeMotionDown();
13477}
13478
13479TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013480 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013481 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013483 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013484 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013485 randosSpy->setSpy(true);
13486 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013487 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013488
13489 // The event is targeted at owner's window, so injection should succeed, but the spy should
13490 // not receive the event.
13491 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13492 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13493 randosSpy->assertNoEvents();
13494 window->consumeMotionDown();
13495}
13496
13497TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013498 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013499 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013500
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013501 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013502 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013503 randosSpy->setSpy(true);
13504 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013505 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013506
13507 // A user that has injection permission can inject into any window.
13508 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013509 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013510 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013511 randosSpy->consumeMotionDown();
13512 window->consumeMotionDown();
13513
13514 setFocusedWindow(randosSpy);
13515 randosSpy->consumeFocusEvent(true);
13516
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013517 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013518 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013519 window->assertNoEvents();
13520}
13521
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013522TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013523 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013524 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013525
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013526 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013527 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013528 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13529 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013530 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013531
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013532 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013533 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13534 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13535 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013536 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013537}
13538
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013539using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13540
13541TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13543
13544 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013545 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013546 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013547 sp<FakeWindowHandle> right =
13548 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13549 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013550 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013551 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13552 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013553 spy->setFrame(Rect(0, 0, 200, 100));
13554 spy->setTrustedOverlay(true);
13555 spy->setSpy(true);
13556
13557 mDispatcher->onWindowInfosChanged(
13558 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13559
13560 // Hover into the left window.
13561 mDispatcher->notifyMotion(
13562 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13563 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13564 .build());
13565
13566 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13567 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13568
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013569 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13570 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013571 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013572 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13573 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013574 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013575 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13576 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013577 /*pointerId=*/0));
13578
13579 // Hover move to the right window.
13580 mDispatcher->notifyMotion(
13581 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13582 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13583 .build());
13584
13585 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13586 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13587 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13588
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013589 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13590 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013591 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013592 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13593 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013594 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013595 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13596 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013597 /*pointerId=*/0));
13598
13599 // Stop hovering.
13600 mDispatcher->notifyMotion(
13601 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13602 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13603 .build());
13604
13605 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13606 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13607
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013608 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13609 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013610 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013611 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13612 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013613 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013614 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13615 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013616 /*pointerId=*/0));
13617}
13618
13619TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13621
13622 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013623 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013624 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013625 sp<FakeWindowHandle> right =
13626 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13627 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013628 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013629 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13630 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013631 spy->setFrame(Rect(0, 0, 200, 100));
13632 spy->setTrustedOverlay(true);
13633 spy->setSpy(true);
13634
13635 mDispatcher->onWindowInfosChanged(
13636 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13637
13638 // First pointer down on left window.
13639 mDispatcher->notifyMotion(
13640 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13641 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13642 .build());
13643
13644 left->consumeMotionDown();
13645 spy->consumeMotionDown();
13646
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013647 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13648 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013649 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013650 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13651 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013652 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013653 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13654 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013655 /*pointerId=*/0));
13656
13657 // Second pointer down on right window.
13658 mDispatcher->notifyMotion(
13659 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13660 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13661 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13662 .build());
13663
13664 left->consumeMotionMove();
13665 right->consumeMotionDown();
13666 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13667
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013668 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13669 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013670 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013671 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13672 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013673 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013674 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13675 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013676 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013677 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13678 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013679 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013680 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13681 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013682 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013683 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13684 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013685 /*pointerId=*/1));
13686
13687 // Second pointer up.
13688 mDispatcher->notifyMotion(
13689 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13690 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13691 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13692 .build());
13693
13694 left->consumeMotionMove();
13695 right->consumeMotionUp();
13696 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13697
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013698 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13699 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013700 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013701 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13702 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013703 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013704 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13705 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013706 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013707 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13708 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013709 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013710 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13711 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013712 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013713 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13714 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013715 /*pointerId=*/1));
13716
13717 // First pointer up.
13718 mDispatcher->notifyMotion(
13719 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13720 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13721 .build());
13722
13723 left->consumeMotionUp();
13724 spy->consumeMotionUp();
13725
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013726 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13727 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013728 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013729 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13730 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013731 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013732 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13733 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013734 /*pointerId=*/0));
13735}
13736
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013737TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13738 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13740
13741 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013742 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013743 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013744 sp<FakeWindowHandle> right =
13745 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13746 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013747 right->setFrame(Rect(100, 0, 200, 100));
13748
13749 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13750
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013751 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13752 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013753 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013754 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13755 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013756 /*pointerId=*/0));
13757
13758 // Hover move into the window.
13759 mDispatcher->notifyMotion(
13760 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13761 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13762 .rawXCursorPosition(50)
13763 .rawYCursorPosition(50)
13764 .deviceId(DEVICE_ID)
13765 .build());
13766
13767 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13768
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013769 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13770 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013771 /*pointerId=*/0));
13772
13773 // Move the mouse with another device. This cancels the hovering pointer from the first device.
13774 mDispatcher->notifyMotion(
13775 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13776 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13777 .rawXCursorPosition(51)
13778 .rawYCursorPosition(50)
13779 .deviceId(SECOND_DEVICE_ID)
13780 .build());
13781
13782 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13783 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13784
13785 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13786 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013787 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13788 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013789 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013790 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013791 SECOND_DEVICE_ID,
13792 /*pointerId=*/0));
13793
13794 // Move the mouse outside the window. Document the current behavior, where the window does not
13795 // receive HOVER_EXIT even though the mouse left the window.
13796 mDispatcher->notifyMotion(
13797 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13798 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13799 .rawXCursorPosition(150)
13800 .rawYCursorPosition(50)
13801 .deviceId(SECOND_DEVICE_ID)
13802 .build());
13803
13804 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13805 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013806 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13807 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013808 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013809 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013810 SECOND_DEVICE_ID,
13811 /*pointerId=*/0));
13812}
13813
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013814/**
13815 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
13816 * the same cursor, and therefore have a shared motion event stream.
13817 */
13818TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
13819 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13821
13822 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013823 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013824 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013825 sp<FakeWindowHandle> right =
13826 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13827 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013828 right->setFrame(Rect(100, 0, 200, 100));
13829
13830 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13831
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013832 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13833 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013834 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013835 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13836 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013837 /*pointerId=*/0));
13838
13839 // Hover move into the window.
13840 mDispatcher->notifyMotion(
13841 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13842 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13843 .rawXCursorPosition(50)
13844 .rawYCursorPosition(50)
13845 .deviceId(DEVICE_ID)
13846 .build());
13847
13848 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13849
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013850 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13851 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013852 /*pointerId=*/0));
13853
13854 // Move the mouse with another device
13855 mDispatcher->notifyMotion(
13856 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13857 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13858 .rawXCursorPosition(51)
13859 .rawYCursorPosition(50)
13860 .deviceId(SECOND_DEVICE_ID)
13861 .build());
13862 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13863
13864 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13865 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013866 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13867 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013868 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013869 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013870 SECOND_DEVICE_ID,
13871 /*pointerId=*/0));
13872
13873 // Move the mouse outside the window. Document the current behavior, where the window does not
13874 // receive HOVER_EXIT even though the mouse left the window.
13875 mDispatcher->notifyMotion(
13876 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13877 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13878 .rawXCursorPosition(150)
13879 .rawYCursorPosition(50)
13880 .deviceId(SECOND_DEVICE_ID)
13881 .build());
13882
13883 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013884 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13885 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013886 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013887 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013888 SECOND_DEVICE_ID,
13889 /*pointerId=*/0));
13890}
13891
Arpit Singhb65e2bd2024-06-03 09:48:16 +000013892TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
13893 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
13894 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
13895}
13896
Garfield Tane84e6f92019-08-29 17:28:41 -070013897} // namespace android::inputdispatcher